#!/usr/bin/env python3
# -*- coding:utf-8 -*-
try:
    import sys
    import os
    import time

    sys.path.append(sys.path[0] + "/../../../../../lib/netifaces/")

    sys.path.append(sys.path[0] + "/../../../../")
    from gspylib.common.ErrorCode import ErrorCode
    from gspylib.component.Kernel.Kernel import Kernel
    from gspylib.os.gsfile import g_file
    from gspylib.os.gsOSlib import g_OSlib
    from gspylib.common.Common import DefaultValue, ClusterInstanceConfig, ConfigGUC

except ImportError as ie:
    sys.exit("[GAUSS-52200] : Unable to import module: %s." % str(ie))

METHOD_TRUST = "trust"
METHOD_SHA = "sha256"
MAX_PARA_NUMBER = 1000
RETRY_COUNT = 3


class CN_OLAP(Kernel):
    '''
    The class is used to define base component.
    '''

    def __init__(self):
        '''
        Constructor
        '''
        self.imageFileExists = False

    def getCnGUCDict(self):
        """
        function : get init CN install guc parameter
        input : String,String,String,int
        output : String
        """
        tmpDict = {}
        if self.imageFileExists:
            tmpDict["pgxc_node_name"] = "'cn_%s'" % self.instInfo.instanceId
        tmpDict["ssl"] = "on"
        tmpDict["ssl_cert_file"] = "'server.crt'"
        tmpDict["ssl_key_file"] = "'server.key'"
        tmpDict["ssl_ca_file"] = "'cacert.pem'"
        return tmpDict

    def copyAndModCertFiles(self):
        """
        function : copy and chage permission cert files
        input : NA
        output : NA
        """
        toolspath = DefaultValue.getEnv(DefaultValue.TOOL_PATH_ENV)
        # cp cert files
        g_file.cpFile("%s/lib/sslcert/server.crt" % toolspath, "%s/" % self.instInfo.datadir)
        g_file.cpFile("%s/lib/sslcert/server.key" % toolspath, "%s/" % self.instInfo.datadir)
        g_file.cpFile("%s/lib/sslcert/cacert.pem" % toolspath, "%s/" % self.instInfo.datadir)
        g_file.cpFile("%s/lib/sslcert/server.key.cipher" % toolspath, "%s/" % self.instInfo.datadir)
        g_file.cpFile("%s/lib/sslcert/server.key.rand" % toolspath, "%s/" % self.instInfo.datadir)
        # change mode
        g_file.changeMode(DefaultValue.KEY_FILE_MODE, "%s/server.crt" % self.instInfo.datadir)
        g_file.changeMode(DefaultValue.KEY_FILE_MODE, "%s/server.key" % self.instInfo.datadir)
        g_file.changeMode(DefaultValue.KEY_FILE_MODE, "%s/cacert.pem" % self.instInfo.datadir)
        g_file.changeMode(DefaultValue.KEY_FILE_MODE, "%s/server.key.cipher" % self.instInfo.datadir)
        g_file.changeMode(DefaultValue.KEY_FILE_MODE, "%s/server.key.rand" % self.instInfo.datadir)

    def initInstance(self):
        """
        function:
            init cn instance
        input:string:dbInitParams
        output:
        """
        if (not os.path.exists(self.instInfo.datadir)):
            raise Exception(ErrorCode.GAUSS_502["GAUSS_50201"] % ("data directory [%s]" % self.instInfo.datadir))

        image_path = DefaultValue.DWS_IMAGE_PATH
        packageName = "%s/coordinator.tar.gz" % image_path
        if self.dwsMode and os.path.exists(packageName):
            self.imageFileExists = True
            g_file.decompressFiles(packageName, self.instInfo.datadir)
        else:
            cmd = "%s/gs_initdb --locale=C -D %s --nodename=cn_%d %s -C %s" % \
                  (self.binPath, self.instInfo.datadir, self.instInfo.instanceId,
                   " ".join(self.initParas), self.binPath)
            self.logger.debug("Command for initializing CN instance: %s" % cmd)
            (status, output) = DefaultValue.retryGetstatusoutput(cmd)
            if (status != 0):
                raise Exception(ErrorCode.GAUSS_516["GAUSS_51615"] + " Command:%s. Error:\n%s" % (cmd, output))
                # set GUC parameter
        cnGucParas = self.getCnGUCDict()
        self.setGucConfig(cnGucParas)
        self.copyAndModCertFiles()

    def getInstanceNodeName(self):
        """
        function: Get Instance Node Name
        input : NA
        output: instance node name
        """
        return "cn_%d" % self.instInfo.instanceId

    def setPghbaConfig(self, clusterAllIpList):
        """
        """
        principal = None
        if (DefaultValue.checkKerberos(DefaultValue.getMpprcFile())):
            (status, output) = g_OSlib.getGrepValue("-Er", "^default_realm",
                                                    os.path.join(os.path.dirname(DefaultValue.getMpprcFile()),
                                                                 DefaultValue.FI_KRB_CONF))
            if (status != 0):
                raise Exception(ErrorCode.GAUSS_502["GAUSS_50222"] % "krb5.conf" + "Error:\n%s" % output)
            principal = output.split("=")[1].strip()

        # build ip string list
        # Every 1000 records merged into one
        i = 0
        GUCParasStr = ""
        GUCParasStrList = []
        for ipAddress in clusterAllIpList:
            i += 1
            # Set the initial user and initial database access permissions
            if (principal is None):
                GUCParasStr += "-h \"%s\" " % ClusterInstanceConfig.getHbaItemForIP(ipAddress, METHOD_TRUST)
            else:
                GUCParasStr += "-h \"%s\" " % \
                               ClusterInstanceConfig.getHbaItemForIP(ipAddress,
                                                                     "gss include_realm=1 krb_realm=%s" % principal)
            if (i % MAX_PARA_NUMBER == 0):
                GUCParasStrList.append(GUCParasStr)
                i = 0
                GUCParasStr = ""

        if (GUCParasStr != ""):
            GUCParasStrList.append(GUCParasStr)

        for parasStr in GUCParasStrList:
            self.doGUCConfig("set", parasStr, True)

    def setSecretFree(self, mode):
        """
        function: Secret-free settings
        input : NA
        output: NA
        """
        # Secret-free settings
        if self.dwsMode:
            self.logger.debug("Begin to set secret free.")
            GUCParasStr = " -h \"host    all    all    %s\"" % (mode)
            self.doGUCConfig("set", GUCParasStr, False)
            self.logger.debug("Set secret free succeeded.")

    def getCNDict(self, user, configItemType=None):
        """
        function: Get CN configuration
        input : NA
        output: NA
        """
        tmpCNDict = {"listen_addresses": "'localhost,%s'" % ",".join(self.instInfo.listenIps),
                     "local_bind_address": "'%s'" % self.instInfo.listenIps[0], "port": str(self.instInfo.port),
                     "comm_control_port": str(self.instInfo.controlPort), "comm_sctp_port": str(self.instInfo.sctpPort)}

        if self.clusterType == DefaultValue.CLUSTER_TYPE_SINGLE_PRIMARY_MULTI_STANDBY:
            tmpCNDict["enable_data_replicate"] = "off"
            tmpCNDict["replication_type"] = "1"
        if self.clusterType == DefaultValue.CLUSTER_TYPE_SINGLE:
            tmpCNDict["replication_type"] = "2"
        if configItemType != "ChangeIPUtility":
            tmpCNDict["pooler_port"] = str(self.instInfo.haPort)
            tmpCNDict["log_directory"] = "'%s/pg_log/cn_%d'" % \
                                         (DefaultValue.getUserLogDirWithUser(user),
                                          self.instInfo.instanceId)
            tmpCNDict["audit_directory"] = "'%s/pg_audit/cn_%d'" % \
                                           (DefaultValue.getUserLogDirWithUser(user),
                                            self.instInfo.instanceId)

        if configItemType != "ConfigInstance" and configItemType != "ChangeIPUtility":
            tmpCNDict["pgxc_node_name"] = "'cn_%d'" % self.instInfo.instanceId

        if len(self.instInfo.ssdDir) != 0 and configItemType != "ChangeIPUtility":
            tmpCNDict["ssd_cache_dir"] = "'%s'" % self.instInfo.ssdDir
            tmpCNDict["enable_adio_function"] = "on"
            tmpCNDict["enable_cstore_ssd_cache"] = "on"

        return tmpCNDict

    def config_dynamic_guc(self, clusterInfo, min_value, set_mode):
        """
        """
        dynamic_dict = ConfigGUC.dynamic_guc("cn", self.clusterType, clusterInfo, min_value, self.instInfo)
        if not dynamic_dict:
            raise Exception(ErrorCode.GAUSS_502["GAUSS_50219"] % "guc_list.conf")
        self.setGucConfig(dynamic_dict, set_mode)

    def configInstance(self, user, cooConfig, gtmList, configItemType=None, alarm_component=None):
        """
        """
        common_dict = self.setCommonItems()
        gtm_dict = ClusterInstanceConfig.setGtmInfo(gtmList)
        tmp_cn_dict = self.getCNDict(user, configItemType)
        tmp_cn_dict.update(cooConfig)
        tmp_cn_dict["alarm_component"] = "'%s'" % alarm_component

        # merge all dict common_dict + gtm_dict + tmp_cn_dict
        # the merge function only spported by at least python 3.5
        real_dict = {**common_dict, **gtm_dict, **tmp_cn_dict}
        self.setGucConfig(real_dict)

    def getGucConfig(self, paraList, user, port, database="postgres", host="", option=""):
        """
        """
        dictList = {}
        parasStr = ""
        for para in paraList:
            parasStr = "%s\'%s\'," % (parasStr, para)
        if parasStr == "":
            return dictList
        parasStr = parasStr[:-1]
        sqlQuery = "SELECT name,setting FROM pg_catalog.pg_settings WHERE name in (%s)" % parasStr
        (status, output) = self.execSQLCommand(sqlQuery, user, host, port, database, option)
        if 0 != status or "" == output:
            raise Exception(str(output))
        for line in output.split('\n'):
            key = line.split('|')[0]
            value = line.split('|')[1]
            if value.isdigit():
                value = int(value)
            dictList[key] = value
        return dictList

    def createNewNode(self, nodeName, instType):
        """
        function: Create new datanode node info
        input : nodeName, instType(C/D)
        output: NA
        """
        self.logger.log("Creating new instance.")
        try:
            createSql = "set application_name='OM';" \
                        "CREATE NODE %s WITH (type='%s', host='localhost', port=%s);" % \
                        (nodeName, instType, self.instInfo.port)
            self.logger.debug("Command for creating new DN node: %s" % createSql)
            self.setSecretFree(METHOD_TRUST)
            (status, output) = self.execSQLCommand(createSql, self.user, "", self.instInfo.port)

            self.logger.debug("Create new node result: %s." % output)
            if (status != 0):
                raise Exception(ErrorCode.GAUSS_513["GAUSS_51300"] % createSql + " Error:\n%s" % output)
            self.reloadPgxcpool(self.user)
            self.setSecretFree(METHOD_SHA)
        except Exception as ex:
            self.setSecretFree(METHOD_SHA)
            raise Exception(str(ex))

    def reloadPgxcpool(self, user):
        """
        function :Reload pgxc_pool
        input : NA
        output: NA
        """
        reloadSql = "SELECT pg_catalog.pgxc_pool_reload();"
        (status, output) = self.execSQLCommand(reloadSql, user, "", self.instInfo.port)
        if (status != 0):
            raise Exception(ErrorCode.GAUSS_513["GAUSS_51300"] % reloadSql + " Error:\n%s" % output)

    def checkNodegroupSet(self, user):
        """
        function: Check if the "default_storage_nodegroup" parameter value
        is the same as the nodegroup of in_redistribution='n'
        output: if True, they are same, else not same.
        """
        self.logger.debug("Checking if the nodegroup parameter settings to meet the requirements.")
        try:
            # get default_storage_nodegroup value
            paraList = ['default_storage_nodegroup']
            dictList = self.getGucConfig(paraList, user, self.instInfo.port)

            # get the nodegroup that is in_redistribution='n' and is_installation = TRUE.
            obtainOldGroupNameSql = "SELECT group_name FROM pg_catalog.pgxc_group " \
                                    "WHERE in_redistribution='y' and is_installation = FALSE;"
            self.logger.debug("Command for getting old node group: %s" % obtainOldGroupNameSql)
            (status, output) = self.execSQLCommand(obtainOldGroupNameSql, user, "", self.instInfo.port)
            if (status != 0):
                raise Exception(ErrorCode.GAUSS_513["GAUSS_51300"] % obtainOldGroupNameSql + " Error:\n%s" % output)

            # Determine whether the two values are equal. Only two values are not equal,
            # in order to make redistribution.
            if (dictList['default_storage_nodegroup'].strip() == output.strip()):
                self.logger.debug("Successfully checked if the nodegroup parameter settings to meet the requirements.")
                return True
            else:
                return False
        except Exception as e:
            raise Exception(str(e))

    def createNewNodeGroup(self, user, group_name, DNNameStr, CNNameStr, isResize=False):
        """
        function: Create new node group
        input : NA
        output: NA
        """
        try:
            # get old nodegroup, is_installation=TRUE
            OBTAIN_OLD_GROUP_SQL = "SELECT group_name FROM pg_catalog.pgxc_group " \
                                   "WHERE in_redistribution='n' and is_installation = TRUE;"
            (status, output) = self.execSQLCommand(OBTAIN_OLD_GROUP_SQL, user, "", self.instInfo.port)
            if (status != 0 or output.strip() == ""):
                raise Exception(ErrorCode.GAUSS_502["GAUSS_50219"] % "old group" + " Error:\n%s" % str(output))
            old_group_name = output.strip()

            START_TRANSACTION_SQL = "SET xc_maintenance_mode = on; START TRANSACTION; "
            CREATE_GROUP_SQL = "CREATE NODE GROUP \"%s\" WITH(%s); "
            if (isResize):
                UPDATE_SQL = "EXECUTE DIRECT ON(%s) 'UPDATE pg_catalog.pgxc_group SET in_redistribution = ''y'' " \
                             "WHERE group_name = ''%s'''; EXECUTE DIRECT ON(%s) 'UPDATE pg_catalog.pgxc_group " \
                             "SET in_redistribution = ''t'' WHERE group_name = ''%s'''; " \
                             "EXECUTE DIRECT ON(%s) 'update pg_catalog.pgxc_group " \
                             "set group_acl= concat(''{'', concat(current_user,''=UCp/'', current_user, " \
                             "'',=UCp/'',current_user), ''}'')::aclitem[] WHERE group_name = ''%s'''; "
            else:
                UPDATE_SQL = "EXECUTE DIRECT ON(%s) 'UPDATE pg_catalog.pgxc_group SET is_installation = FALSE , " \
                             "in_redistribution = ''y'',group_kind=''n'' WHERE group_name = ''%s'''; " \
                             "EXECUTE DIRECT ON(%s) 'UPDATE pg_catalog.pgxc_group SET is_installation = TRUE , " \
                             "in_redistribution = ''n'',group_kind=''i'' WHERE group_name = ''%s'''; " \
                             "EXECUTE DIRECT ON(%s) 'update pg_catalog.pgxc_group set group_acl= concat(''{'', " \
                             "concat(current_user,''=UCp/'', current_user, '',=UCp/'',current_user), " \
                             "''}'')::aclitem[] WHERE group_name = ''%s'''; "
            END_TRANSACTION_SQL = "COMMIT; RESET xc_maintenance_mode;"

            create_sql = CREATE_GROUP_SQL % (group_name, DNNameStr)
            update_sql = ""
            for cnname in CNNameStr.split(','):
                update_sql += UPDATE_SQL % (cnname, old_group_name, cnname, group_name, cnname, group_name)
            sql = "%s%s%s%s" % (START_TRANSACTION_SQL, create_sql, update_sql, END_TRANSACTION_SQL)
            self.logger.debug("Sql cmmand for create pgxc_group: %s" % sql)
            # create new group
            (status, output) = self.execSQLCommand(sql, user, "", self.instInfo.port)
            if (status != 0):
                raise Exception(ErrorCode.GAUSS_514["GAUSS_51400"] % sql + " Error:\n%s" % str(output))
        except Exception as e:
            raise Exception(str(e))
        self.logger.log("Successfully created new node group.")

    def deleteOldNodeGroup(self, user):
        """
        function: Drop old node group
        input : NA
        output: NA
        """
        START_TRANSACTION_SQL = "SET xc_maintenance_mode = on; START TRANSACTION; "
        DELETE_GROUP_SQL = "DROP NODE GROUP %s;"
        END_TRANSACTION_SQL = "COMMIT; RESET xc_maintenance_mode;"

        self.logger.log("Deleting old node group.")

        # 1.get old nodegroup, in_redistribution='y'
        obtainOldGroupNameSql = "SELECT group_name FROM pg_catalog.pgxc_group " \
                                "WHERE in_redistribution='y' and is_installation = FALSE;"
        self.logger.debug("Command for getting old node group: %s" % obtainOldGroupNameSql)
        (status, output) = self.execSQLCommand(obtainOldGroupNameSql, user, "", self.instInfo.port)
        if (status != 0):
            raise Exception(ErrorCode.GAUSS_502["GAUSS_50219"] % "old group" + " Error:\n%s" % str(output))
        if (output.strip() == ""):
            self.logger.debug("The nodegroup to delete is empty. The current operation may be performing re-entry.")
            return
        oldGroupName = output.strip()

        retryTime = 3
        jobCheckSql = "SELECT count(*) FROM pg_catalog.pg_session_wlmstat WHERE node_group = '%s';" % oldGroupName
        self.logger.debug("Command for checking job on group %s: %s" % (oldGroupName, jobCheckSql))
        for i in range(retryTime):
            status, output = self.execSQLCommand(jobCheckSql, user, "", self.instInfo.port)
            if status != 0 or not output.isdigit():
                self.logger.debug("Failed to execute SQL \"%s\" %d times" % (jobCheckSql, i + 1))
                time.sleep(1)
            elif int(output.strip()) > 0:
                self.logger.debug("There has %d job on %s. "
                                  "The current operation may be performing re-entry." %
                                  (int(output.strip()), oldGroupName))
                time.sleep(10)
            else:
                break
        if status != 0 or not output.isdigit():
            raise Exception(ErrorCode.GAUSS_513["GAUSS_51300"] % jobCheckSql + " Error: \n%s" % str(output))
        if int(output.strip()) > 0:
            raise Exception(ErrorCode.GAUSS_516["GAUSS_51632"] % "node group deleting" +
                            " There has %d job on %s." %
                            (int(output.strip()), oldGroupName))

        # sql command: drop old node group
        deleteSql = DELETE_GROUP_SQL % oldGroupName

        executeSql = "%s%s%s" % (START_TRANSACTION_SQL, deleteSql, END_TRANSACTION_SQL)
        self.logger.debug("Sql command for deleting old node group: %s" % executeSql)
        # delete old node group
        for i in range(retryTime):
            status, output = self.execSQLCommand(executeSql, user, "", self.instInfo.port)
            if status != 0:
                self.logger.debug("Failed to execute SQL \"%s\" %d times" % (executeSql, i + 1))
                time.sleep(3)
            else:
                break
        if status != 0:
            raise Exception(ErrorCode.GAUSS_513["GAUSS_51300"] % executeSql + " Error: \n%s" % str(output))

        self.logger.log("Successfully deleted old node group.")

    def updatePgxcNodeInfo(self, user):
        """
        update the pgxc_node information for all instance
        """
        START_TRANSACTION_SQL = "SET xc_maintenance_mode = on; "
        UPDATE_SQL = "UPDATE pg_catalog.pgxc_node SET (node_port, node_port1, sctp_port, control_port, " \
                     "sctp_port1, control_port1)=('%d','%d','%d','%d','0','0') " \
                     "WHERE node_name='cn_%s';" % (self.instInfo.port,
                                                   self.instInfo.port,
                                                   self.instInfo.sctpPort,
                                                   self.instInfo.controlPort,
                                                   self.instInfo.instanceId)
        END_TRANSACTION_SQL = "RESET xc_maintenance_mode;"
        executeSql = "%s%s%s" % (START_TRANSACTION_SQL, UPDATE_SQL, END_TRANSACTION_SQL)
        self.logger.log("Updating pgxc_node information.")
        self.logger.log("Sql command for updating pgxc_node: %s" % executeSql)
        (status, output) = self.execSQLCommand(executeSql, user, "", self.instInfo.port)
        if status != 0:
            raise Exception(ErrorCode.GAUSS_513["GAUSS_51300"] % executeSql + " Error: \n%s" % str(output))
        self.reloadPgxcpool(user)
        self.logger.log("Successfully updated pgxc_node.")

    def getExistsInstNodeNameList(self, user):
        """
        """
        SELECT_SQL = "SELECT node_name FROM pg_catalog.pgxc_node ORDER BY node_name"
        self.logger.debug("Sql command for selecting exists pgxc_node: %s" % SELECT_SQL)
        (status, output) = self.execSQLCommand(SELECT_SQL, user, "", self.instInfo.port)
        if status != 0:
            raise Exception(ErrorCode.GAUSS_513["GAUSS_51300"] % SELECT_SQL + " Error: \n%s" % str(output))
        self.logger.debug("Exists pgxc_node: %s" % output)
        return output.split('\n')

    def createPgxcNodeInfo(self, user, instDict, readonly=False):
        """
        create new node group all CNs
        value : node_host, node_host1, node_port, node_port1, sctp_port, control_port, sctp_port1, control_port1
        """
        existsNodeNames = self.getExistsInstNodeNameList(user)
        START_TRANSACTION_SQL = "SET xc_maintenance_mode = on; "
        END_TRANSACTION_SQL = "RESET xc_maintenance_mode;"
        for instStr in instDict.keys():
            instType = instStr.split('|')[0]
            instName = instStr.split('|')[1]
            if instName in existsNodeNames:
                continue
            if instType == 'C':
                typeStr = "type='coordinator'"
            elif instType == 'D':
                typeStr = "type='datanode', rw=true"
            else:
                typeStr = "type='datanode', rw=false"

            CREATE_NODE_SQL = "CREATE NODE %s WITH (%s, host='%s', host1='%s', port=%s, port1=%s, " \
                              "sctp_port=%s,control_port=%s, sctp_port1=%s, control_port1=%s)" % \
                              (instName, typeStr,
                               instDict[instStr].split('|')[0],
                               instDict[instStr].split('|')[1],
                               instDict[instStr].split('|')[2],
                               instDict[instStr].split('|')[3],
                               instDict[instStr].split('|')[4],
                               instDict[instStr].split('|')[5],
                               instDict[instStr].split('|')[6],
                               instDict[instStr].split('|')[7])
            if readonly:
                CREATE_NODE_SQL += " READ ONLY;"
            else:
                CREATE_NODE_SQL += ";"
            executeSql = "%s%s%s" % (START_TRANSACTION_SQL, CREATE_NODE_SQL, END_TRANSACTION_SQL)
            self.logger.log("Creating pgxc_node information.")
            self.logger.log("Sql command for creating pgxc_node: %s" % executeSql)
            (status, output) = self.execSQLCommand(executeSql, user, "", self.instInfo.port)
            if status != 0:
                raise Exception(ErrorCode.GAUSS_513["GAUSS_51300"] % executeSql + " Error: \n%s" % str(output))
        self.reloadPgxcpool(user)
        self.logger.log("Successfully created pgxc_node.")

    def createPgxcGroupInfo(self, user, group_name, DNNameStr):
        """
        create new pgxc_group for all CNs
        /*
         * "CREATE NODE GROUP" is distributed sql which
         * be executed on all CN, so it should get snapshot
         * from GTM(xc_maintenance_mode=off),
         * not from local cn(xc_maintenance_mode=on)
         */
        """
        START_TRANSACTION_SQL = "SET xc_maintenance_mode = off; START TRANSACTION; "
        CREATE_GROUP_SQL = "CREATE NODE GROUP \"%s\" WITH(%s); " % (
            group_name, DNNameStr)
        UPDATE_GROUP_SQL1 = "UPDATE pg_catalog.pgxc_group SET is_installation = TRUE " \
                            "WHERE group_name = '%s'; " % group_name
        UPDATE_GROUP_SQL2 = "UPDATE pg_catalog.pgxc_group SET group_kind = 'i' WHERE group_name = '%s'; " % group_name
        UPDATE_GROUP_SQL3 = "UPDATE pg_catalog.pgxc_group SET group_acl = concat('{', concat(current_user,'=UCp/', " \
                            "current_user, ',=UCp/',current_user), '}')::aclitem[] " \
                            "WHERE group_name = '%s';" % group_name
        END_TRANSACTION_SQL = "COMMIT; RESET xc_maintenance_mode;"
        executeSql = "%s%s%s%s%s%s" % (START_TRANSACTION_SQL, CREATE_GROUP_SQL,
                                       UPDATE_GROUP_SQL1, UPDATE_GROUP_SQL2, UPDATE_GROUP_SQL3, END_TRANSACTION_SQL)
        self.logger.log("Creating pgxc_group information.")
        self.logger.log("Sql command for creating pgxc_group: %s" % executeSql)
        (status, output) = self.execSQLCommand(executeSql, user, "", self.instInfo.port)
        if status != 0:
            raise Exception(ErrorCode.GAUSS_513["GAUSS_51300"] % executeSql + " Error: \n%s" % str(output))
        self.reloadPgxcpool(user)
        self.logger.log("Successfully created pgxc_group.")

    def updataPgxcInfoForLC(self, user, DNNameStr):
        """
        """
        START_TRANSACTION_SQL = "SET xc_maintenance_mode = off;"
        DROP_SQL = "SET application_name='OM';"
        for dnName in DNNameStr.split(','):
            DROP_SQL = "%sDROP NODE IF EXISTS %s;" % (DROP_SQL, dnName)
        END_TRANSACTION_SQL = "RESET xc_maintenance_mode;"

        executeSql = "%s%s%s" % (START_TRANSACTION_SQL, DROP_SQL, END_TRANSACTION_SQL)
        self.logger.log("Refreshing logical cluster pgxc info.")
        self.logger.log("Sql command for refresh logical cluster pgxc info: %s" % executeSql)
        (status, output) = self.execSQLCommand(executeSql, user, "", self.instInfo.port)
        if status != 0:
            raise Exception(ErrorCode.GAUSS_513["GAUSS_51300"] % executeSql + " Error: \n%s" % str(output))
        self.reloadPgxcpool(user)
        self.logger.log("Successfully refresh logical cluster pgxc info.")

    def deleteNodeInfo(self, user, instDict):
        """
        """
        START_TRANSACTION_SQL = "SET xc_maintenance_mode = on; "
        instNameList = []
        for instStr in instDict.keys():
            instName = instStr.split('|')[1]
            instNameList.append(instName)
        instNameList = list(set(instNameList))
        DELETE_NODE_SQL = ""
        for instName in instNameList:
            DELETE_NODE_SQL = "%s DROP NODE IF EXISTS %s WITH(cn_%s); " % (DELETE_NODE_SQL,
                                                                           instName,
                                                                           self.instInfo.instanceId)
        END_TRANSACTION_SQL = "RESET xc_maintenance_mode;"
        executeSql = "%s%s%s" % (START_TRANSACTION_SQL, DELETE_NODE_SQL, END_TRANSACTION_SQL)
        self.logger.log("Deleting pgxc_node information.")
        self.logger.log("Sql command for deleting pgxc_node: %s" % executeSql)
        (status, output) = self.execSQLCommand(executeSql, user, "", self.instInfo.port)
        if status != 0:
            raise Exception(ErrorCode.GAUSS_513["GAUSS_51300"] % executeSql + " Error: \n%s" % str(output))
        self.reloadPgxcpool(user)
        self.logger.log("Successfully deleted pgxc_node.")
