From 14bc8a3c91565ae31af83ae8d3ee519199a93974 Mon Sep 17 00:00:00 2001 From: xue_meng_en <1836611252@qq.com> Date: Tue, 18 Oct 2022 11:40:59 +0800 Subject: [PATCH] =?UTF-8?q?cm=E5=AE=89=E8=A3=85=E8=A7=A3=E8=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build/build.sh | 3 +- tool/cm_tool/CMLog.py | 398 ++++++++++++ tool/cm_tool/Common.py | 42 ++ tool/cm_tool/ErrorCode.py | 1173 +++++++++++++++++++++++++++++++++++ tool/cm_tool/InstallImpl.py | 307 +++++++++ tool/cm_tool/__init__.py | 0 tool/cm_tool/cm_install | 247 ++++++++ tool/cm_tool/cm_uninstall | 249 ++++++++ 8 files changed, 2418 insertions(+), 1 deletion(-) create mode 100644 tool/cm_tool/CMLog.py create mode 100644 tool/cm_tool/Common.py create mode 100644 tool/cm_tool/ErrorCode.py create mode 100644 tool/cm_tool/InstallImpl.py create mode 100644 tool/cm_tool/__init__.py create mode 100644 tool/cm_tool/cm_install create mode 100644 tool/cm_tool/cm_uninstall diff --git a/build/build.sh b/build/build.sh index 182df46..7120444 100644 --- a/build/build.sh +++ b/build/build.sh @@ -150,7 +150,8 @@ function pkg() { fi cd ${OUT_PATH} - tar -czf "${bin_tar}" bin lib share + cp ${PROJECT_ROOT_PATH}/tool . -R + tar -czf "${bin_tar}" bin lib share tool if [ -d symbols ]; then tar -czf "${sym_tar}" symbols fi diff --git a/tool/cm_tool/CMLog.py b/tool/cm_tool/CMLog.py new file mode 100644 index 0000000..a05ef1a --- /dev/null +++ b/tool/cm_tool/CMLog.py @@ -0,0 +1,398 @@ +# -*- coding:utf-8 -*- +############################################################################# +# Portions Copyright (c) 2022 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 : CMLog.py is utility to handle the log +############################################################################# +import os +import sys +import datetime +import subprocess +import _thread as thread +import re +import logging.handlers as _handlers +import time + +sys.path.append(sys.path[0] + "/../../") + +from ErrorCode import ErrorCode + +# import typing for comment. +try: + from typing import Dict + from typing import List +except ImportError: + Dict = dict + List = list + +# max log file size +# 16M +MAXLOGFILESIZE = 16 * 1024 * 1024 + +LOG_DEBUG = 1 +LOG_INFO = 2 +LOG_WARNING = 2.1 +LOG_ERROR = 3 +LOG_FATAL = 4 + + +class CMLog: + """ + Class to handle log file + """ + + def __init__(self, logPath, module, prefix, suffix = ".log", expectLevel=LOG_DEBUG, traceId=None): + """ + function: Constructor + input : NA + output: NA + """ + self.logFile = "" + self.expectLevel = expectLevel + self.moduleName = module + self.fp = None + self.size = 0 + self.suffix = suffix + self.prefix = prefix + self.logPath = logPath + self.pid = os.getpid() + self.step = 0 + self.lock = thread.allocate_lock() + self.tmpFile = None + self.ignoreErr = False + self.traceId = traceId + + try: + if not os.path.isdir(logPath): + print(ErrorCode.GAUSS_502["GAUSS_50211"] % logPath) + sys.exit(1) + # check log path + if not os.path.exists(logPath): + try: + os.makedirs(logPath, 0o700) + except Exception as e: + raise Exception(ErrorCode.GAUSS_502["GAUSS_50208"] % + logPath + " Error:\n%s" % str(e)) + # create new log file + self.__openLogFile() + except Exception as ex: + print(str(ex)) + sys.exit(1) + + def __checkLink(self): + """ + function: check log file is link + input : NA + output: list of + """ + if os.path.islink(self.logFile): + raise Exception(ErrorCode.GAUSS_502["GAUSS_50206"] % self.logFile) + + def __checkLogFileExist(self): + """ + check whether log file exists, if exist, get log file name + log file name format: + prefix-YYYY-mm-DD_HHMMSSsuffix = cm_install-YYYY-mm-DD_HHMMSS.log + """ + logFileList = "%s/logFileList_%s.dat" % (self.logPath, self.pid) + cmd = "ls %s | grep '^%s-.*%s$' > %s" % ( + self.logPath, self.prefix, self.suffix, logFileList) + (status, output) = subprocess.getstatusoutput(cmd) + if status != 0: + if os.path.exists(logFileList): + os.remove(logFileList) + return False + with open(logFileList, "r") as fp: + filenameList = [] + while True: + # get real file name + filename = (fp.readline()).strip() + if not filename: + break + existedResList = filename.split(".") + if len(existedResList) > 2: + continue + (existedPrefix, existedSuffix) = \ + os.path.splitext(filename) + if existedSuffix != self.suffix: + continue + if len(filename) != len(self.prefix) + \ + len(self.suffix) + 18: + continue + timeStamp = existedPrefix[-17:] + # check log file name + if self.__isValidDate(timeStamp): + filenameList.append(filename) + # cleanup logFileList + if os.path.exists(logFileList): + os.remove(logFileList) + + if len(filenameList) == 0: + return False + # get logFile + fileName = max(filenameList) + self.logFile = os.path.join(self.logPath, fileName) + self.__checkLink() + return True + + def __openLogFile(self): + """ + function: open log file + input : NA + output: NA + """ + try: + if self.__checkLogFileExist(): + self.fp = open(self.logFile, "a") + return + # get current time + currentTime = time.strftime("%Y-%m-%d_%H%M%S") + # init log file + self.logFile = os.path.join(self.logPath, self.prefix + "-" + currentTime + self.suffix) + # Re-create the log file to add a retry 3 times mechanism, + # in order to call concurrently between multiple processes + retryTimes = 3 + count = 0 + while (True): + (status, output) = self.__createLogFile() + if status == 0: + break + count = count + 1 + time.sleep(1) + if (count > retryTimes): + raise Exception(output) + # open log file + self.__checkLink() + self.fp = open(self.logFile, "a") + except Exception as e: + raise Exception(ErrorCode.GAUSS_502["GAUSS_50206"] + % self.logFile + " Error:\n%s" % str(e)) + + def __createLogFile(self): + """ + function: create log file + input : NA + output: (status, output) + """ + try: + if (not os.path.exists(self.logFile)): + os.mknod(self.logFile) + return (0, "") + except Exception as e: + return (1, str(e)) + + def __isValidDate(self, datastr): + """ + function: Judge if date valid + input : datastr + output: bool + """ + try: + time.strptime(datastr, "%Y-%m-%d_%H%M%S") + return True + except Exception as ex: + return False + + def closeLog(self): + """ + function: Function to close log file + input : NA + output: NA + """ + try: + if self.fp: + self.fp.flush() + self.fp.close() + self.fp = None + except Exception as ex: + if self.fp: + self.fp.close() + raise Exception(str(ex)) + + # print the flow message to console window and log file + # AddInfo: constant represent step constant, addStep represent step + # plus, None represent no step + def log(self, msg, stepFlag=""): + """ + function:print the flow message to console window and log file + input: msg,stepFlag + control: when stepFlag="", the OM background log does not display + step information. + when stepFlag="addStep", the OM background log step will + add 1. + when stepFlag="constant", the OM background log step + defaults to the current step. + output: NA + """ + if (LOG_INFO >= self.expectLevel): + print(msg) + self.__writeLog("LOG", msg, stepFlag) + + # print the flow message to log file only + def debug(self, msg, stepFlag=""): + """ + function:print the flow message to log file only + input: msg,stepFlag + control: when stepFlag="", the OM background log does not display + step information. + when stepFlag="addStep", the OM background log step will + add 1. + when stepFlag="constant", the OM background log step + defaults to the current step. + output: NA + """ + if (LOG_DEBUG >= self.expectLevel): + self.__writeLog("DEBUG", msg, stepFlag) + + def warn(self, msg, stepFlag=""): + """ + function:print the flow message to log file only + input: msg,stepFlag + control: when stepFlag="", the OM background log does not display + step information. + when stepFlag="addStep", the OM background log step will + add 1. + when stepFlag="constant", the OM background log step + defaults to the current step. + output: NA + """ + if (LOG_WARNING >= self.expectLevel): + print(msg) + self.__writeLog("WARNING", msg, stepFlag) + + # print the error message to console window and log file + def error(self, msg): + """ + function: print the error message to console window and log file + input : msg + output: NA + """ + if (LOG_ERROR >= self.expectLevel): + print(msg) + self.__writeLog("ERROR", msg) + + # print the error message to console window and log file,then exit + def logExit(self, msg): + """ + function: print the error message to console window and log file, + then exit + input : msg + output: NA + """ + if (LOG_FATAL >= self.expectLevel): + print(msg) + try: + self.__writeLog("ERROR", msg) + except Exception as ex: + print(str(ex)) + self.closeLog() + sys.exit(1) + + def Step(self, stepFlag): + """ + function: return Step number info + input: add + output: step number + """ + if (stepFlag == "constant"): + return self.step + else: + self.step = self.step + 1 + return self.step + + def __getLogFileLine(self): + f = sys._getframe().f_back.f_back.f_back + return "%s(%s:%s)" % (os.path.basename(f.f_code.co_filename), f.f_code.co_name, + str(f.f_lineno)) + + def __writeLog(self, level, msg, stepFlag=""): + """ + function: Write log to file + input: level, msg, stepFlag + output: NA + """ + if self.fp is None: + return + + try: + self.lock.acquire() + # if the log file does not exits, create it + if (not os.path.exists(self.logFile)): + self.__openLogFile() + else: + logPer = oct(os.stat(self.logFile).st_mode)[-3:] + self.__checkLink() + if not logPer == "600": + os.chmod(self.logFile, 0o600) + # check if need switch to an new log file + self.size = os.path.getsize(self.logFile) + if self.size >= MAXLOGFILESIZE and os.getuid() != 0: + self.closeLog() + self.__openLogFile() + + replaceReg = re.compile(r'-W[ ]*[^ ]*[ ]*') + msg = replaceReg.sub('-W *** ', str(msg)) + + if msg.find("gs_redis") >= 0: + replaceReg = re.compile(r'-A[ ]*[^ ]*[ ]*') + msg = replaceReg.sub('-A *** ', str(msg)) + + strTime = datetime.datetime.now() + fileLine = self.__getLogFileLine() + if stepFlag == "": + if self.traceId: + print("[%s][%s][%d][%s][%s]:%s" + % (self.traceId, strTime, self.pid, self.moduleName, + level, msg), file=self.fp) + else: + print("[%s][%d][%s][%s]:%s" % ( + strTime, self.pid, self.moduleName, level, msg), + file=self.fp) + else: + stepnum = self.Step(stepFlag) + print("[%s][%d][%s][%s][%s][Step%d]:%s" % ( + strTime, self.pid, fileLine, self.moduleName, level, stepnum, msg), + file=self.fp) + self.fp.flush() + self.lock.release() + except Exception as ex: + self.lock.release() + if self.ignoreErr: + return + raise Exception(ErrorCode.GAUSS_502["GAUSS_50205"] + % (("log file %s") % self.logFile) + + " Error:\n%s" % str(ex)) + + @staticmethod + def exitWithError(msg, status=1): + """ + function: Exit with error message + input: msg, status=1 + output: NA + """ + sys.stderr.write("%s\n" % msg) + sys.exit(status) + + @staticmethod + def printMessage(msg): + """ + function: Print the String message + input: msg + output: NA + """ + sys.stdout.write("%s\n" % msg) + + diff --git a/tool/cm_tool/Common.py b/tool/cm_tool/Common.py new file mode 100644 index 0000000..7f6377a --- /dev/null +++ b/tool/cm_tool/Common.py @@ -0,0 +1,42 @@ +# -*- coding:utf-8 -*- +############################################################################# +# Copyright (c) 2022 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 : Common.py includes some public function +############################################################################# + +import subprocess +from CMLog import CMLog +from ErrorCode import ErrorCode + +def getEnvParam(envFile, param): + cmd = "source {envFile}; echo ${param}".format(envFile=envFile, param=param) + status, output = subprocess.getstatusoutput(cmd) + if status != 0: + errorDetail = "\nCommand: %s\nStatus: %s\nOutput: %s\n" % ( + cmd, status, output) + CMLog.exitWithError(ErrorCode.GAUSS_518["GAUSS_51802"] % param) + return output + +def getLocalhostName(): + import socket + return socket.gethostname() + +def executeCmdOnHost(host, cmd, isLocal = False): + if not isLocal: + cmd = 'ssh -o ConnectTimeout=5 %s \"%s\"' % (host, cmd) + status, output = subprocess.getstatusoutput(cmd) + return status, output diff --git a/tool/cm_tool/ErrorCode.py b/tool/cm_tool/ErrorCode.py new file mode 100644 index 0000000..05e297a --- /dev/null +++ b/tool/cm_tool/ErrorCode.py @@ -0,0 +1,1173 @@ +# -*- 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 : ErrorCode.py is utility to register the error message +############################################################################# +import re +import sys + + +class ErrorCode(): + """ + Class to define output about the error message + """ + + def __init__(self): + pass + + @staticmethod + def getErrorCodeAsInt(ex, default_error_code): + """ + Resolve the exit code from the exception instance or error message. + + In linux, the range of return values is between 0 and 255. + So we can only use each type of error code as exit code.Such as: + ErrorCode.GAUSS_500 : 10 + ErrorCode.GAUSS_501 : 11 + + :param ex: Exception instance or error message + :param default_error_code: If the exception instance does not contain + the exit code, use this parameter. + + :type ex: Exception | str + :type default_error_code: int + + :return: Return the error code. + 9 represents undefined exit code. + other number between 0 and 255 represent the specific gauss error. + :type: int + """ + error_message = str(ex) + pattern = r"^[\S\s]*\[GAUSS-(\d+)\][\S\s]+$" + match = re.match(pattern, error_message) + + if match is not None and len(match.groups()) == 1: + error_code = int(match.groups()[0]) + else: + error_code = default_error_code + + if 50000 < error_code < 60000: + return error_code // 100 - 500 + 10 + else: + return 9 + + ########################################################################### + # parameter + ########################################################################### + GAUSS_500 = { + 'GAUSS_50000': "[GAUSS-50000] : Unrecognized parameter: %s.", + 'GAUSS_50001': "[GAUSS-50001] : Incorrect parameter. Parameter " + "'-%s' is required", + 'GAUSS_50002': "[GAUSS-50002] : Incorrect parameter. Parameter " + "'-%s' is not required", + 'GAUSS_50003': "[GAUSS-50003] : The parameter '-%s' type should be " + "%s.", + 'GAUSS_50004': "[GAUSS-50004] : The parameter '-%s' value is " + "incorrect.", + 'GAUSS_50005': "[GAUSS-50005] : The parameter '-%s' and '-%s' " + "can not be used together.", + 'GAUSS_50006': "[GAUSS-50006] : Too many command-line arguments " + "(first is \"%s\").", + 'GAUSS_50007': "[GAUSS-50007] : Failed to set %s parameter.", + 'GAUSS_50008': "[GAUSS-50008] : Failed to reload parameter.", + 'GAUSS_50009': "[GAUSS-50009] : Parameter format error.", + 'GAUSS_50010': "[GAUSS-50010] : Failed to check %s parameter.", + 'GAUSS_50011': "[GAUSS-50011] : The parameter[%s] value[%s] " + "is invalid.", + 'GAUSS_50012': "[GAUSS-50012] : The parameter '%s' value can't " + "be empty.", + 'GAUSS_50013': "[GAUSS-50013] : The parameter '%s' have not " + "been initialized.", + 'GAUSS_50014': "[GAUSS-50014] : Parameters of '%s' can not be empty.", + 'GAUSS_50015': "[GAUSS-50015] : The command line parser error: %s.", + 'GAUSS_50016': "[GAUSS-50016] : The re-entrant parameter '-%s' " + "is not same with the previous command.", + 'GAUSS_50017': "[GAUSS-50017] : Incorrect value '%s' specified " + "by the parameter '-%s'.", + 'GAUSS_50018': "[GAUSS-50018] : The parameter value of %s is Null.", + 'GAUSS_50019': "[GAUSS-50019] : The value of %s is error.", + 'GAUSS_50020': "[GAUSS-50020] : The value of %s must be a digit.", + 'GAUSS_50021': "[GAUSS-50021] : Failed to query %s parameter.", + 'GAUSS_50022': "[GAUSS-50022] : The parameter '%s' should be %s.", + 'GAUSS_50023': "[GAUSS-50023] : The parameter '%s' over max length %s.", + 'GAUSS_50024': "[GAUSS-50024] : The parameter '%s' is invalid.", + 'GAUSS_50025': "[GAUSS-50025] : There is illegal character '%s' in parameter %s.", + 'GAUSS_50026': "[GAUSS-50026] : Failed to check %s parameters in the XML file." + + } + + ########################################################################### + # permission + ########################################################################### + GAUSS_501 = { + 'GAUSS_50100': "[GAUSS-50100] : The %s is not readable for %s.", + 'GAUSS_50101': "[GAUSS-50101] : The %s is not executable for %s.", + 'GAUSS_50102': "[GAUSS-50102] : The %s is not writable for %s.", + 'GAUSS_50103': "[GAUSS-50103] : The %s has unexpected rights.", + 'GAUSS_50104': "[GAUSS-50104] : Only a user with the root permission " + "can run this script.", + 'GAUSS_50105': "[GAUSS-50105] : Cannot run this script as a user " + "with the root permission.", + 'GAUSS_50106': "[GAUSS-50106] : Failed to change the owner of %s.", + 'GAUSS_50107': "[GAUSS-50107] : Failed to change the " + "permission of %s.", + 'GAUSS_50108': "[GAUSS-50108] : Failed to change the owner and " + "permission of %s.", + 'GAUSS_50109': "[GAUSS-50109] : Only a user with the root permission " + "can check SSD information.", + 'GAUSS_50110': "[GAUSS-50110] : Cannot execute this script on %s." + } + + ########################################################################### + # file or directory + ########################################################################### + GAUSS_502 = { + 'GAUSS_50200': "[GAUSS-50200] : The %s already exists.", + 'GAUSS_50201': "[GAUSS-50201] : The %s does not exist.", + 'GAUSS_50202': "[GAUSS-50202] : The %s must be empty.", + 'GAUSS_50203': "[GAUSS-50203] : The %s cannot be empty.", + 'GAUSS_50204': "[GAUSS-50204] : Failed to read %s.", + 'GAUSS_50205': "[GAUSS-50205] : Failed to write %s.", + 'GAUSS_50206': "[GAUSS-50206] : Failed to create %s.", + 'GAUSS_50207': "[GAUSS-50207] : Failed to delete %s.", + 'GAUSS_50208': "[GAUSS-50208] : Failed to create the %s directory.", + 'GAUSS_50209': "[GAUSS-50209] : Failed to delete the %s directory.", + 'GAUSS_50210': "[GAUSS-50210] : The %s must be a file.", + 'GAUSS_50211': "[GAUSS-50211] : The %s must be a directory.", + 'GAUSS_50212': "[GAUSS-50212] : The suffix of the file [%s] " + "should be '%s'.", + 'GAUSS_50213': "[GAUSS-50213] : The %s path must be an absolute path.", + 'GAUSS_50214': "[GAUSS-50214] : Failed to copy %s.", + 'GAUSS_50215': "[GAUSS-50215] : Failed to back up %s.", + 'GAUSS_50216': "[GAUSS-50216] : Failed to remote copy %s.", + 'GAUSS_50217': "[GAUSS-50217] : Failed to decompress %s.", + 'GAUSS_50218': "[GAUSS-50218] : Failed to rename %s.", + 'GAUSS_50219': "[GAUSS-50219] : Failed to obtain %s.", + 'GAUSS_50220': "[GAUSS-50220] : Failed to restore %s.", + 'GAUSS_50221': "[GAUSS-50221] : Failed to obtain file type.", + 'GAUSS_50222': "[GAUSS-50222] : The content of file %s is not " + "correct.", + 'GAUSS_50223': "[GAUSS-50223] : Failed to update %s files.", + 'GAUSS_50224': "[GAUSS-50224] : The file name is incorrect.", + 'GAUSS_50225': "[GAUSS-50225] : Failed to back up remotely.", + 'GAUSS_50226': "[GAUSS-50226] : Failed to restore remotely.", + 'GAUSS_50227': "[GAUSS-50227] : Failed to compress %s.", + 'GAUSS_50228': "[GAUSS-50228] : The %s does not exist or is empty.", + 'GAUSS_50229': "[GAUSS-50229] : Cannot specify the file [%s] to " + "the cluster path %s.", + 'GAUSS_50230': "[GAUSS-50230] : Failed to read/write %s.", + 'GAUSS_50231': "[GAUSS-50231] : Failed to generate %s file.", + 'GAUSS_50232': "[GAUSS-50232] : The instance directory [%s] " + "cannot set in app directory [%s].Please check " + "the xml.", + 'GAUSS_50233': "[GAUSS-50233] : The directory name %s and %s " + "cannot be same.", + 'GAUSS_50234': "[GAUSS-50234] : Cannot execute the script in " + "the relevant path of the database.", + 'GAUSS_50235': "[GAUSS-50235] : The log file name [%s] can not contain" + " more than one '.'.", + 'GAUSS_50236': "[GAUSS-50236] : The %s does not exist or " + "the permission on the upper-layer directory is insufficient.", + 'GAUSS_50237': "[GAUSS-50237] : Send result file failed nodes: %s;" + " outputMap: %s", + 'GAUSS_50238': "[GAUSS-50238] : Check integrality of bin ", + "file %s failed." + 'GAUSS_50239': "[GAUSS-50236] : %s should be set in scene config " + "file." + + } + + ########################################################################### + # user and group + ########################################################################### + GAUSS_503 = { + 'GAUSS_50300': "[GAUSS-50300] : User %s does not exist.", + 'GAUSS_50301': "[GAUSS-50301] : The cluster user/group cannot " + "be a root user/group.", + 'GAUSS_50302': "[GAUSS-50302] : The cluster user cannot be a user " + "with the root permission.", + 'GAUSS_50303': "[GAUSS-50303] : Cannot install the program as a " + "user with the root permission.", + 'GAUSS_50304': "[GAUSS-50304] : The new user [%s] is not the same " + "as the old user [%s].", + 'GAUSS_50305': "[GAUSS-50305] : The user is not matched with the " + "user group.", + 'GAUSS_50306': "[GAUSS-50306] : The password of %s is incorrect.", + 'GAUSS_50307': "[GAUSS-50307] : User password has expired.", + 'GAUSS_50308': "[GAUSS-50308] : Failed to obtain user information.", + 'GAUSS_50309': "[GAUSS-50309] : Failed to obtain password " + "change times of data base super user", + 'GAUSS_50310': "[GAUSS-50310] : Failed to obtain password " + "expiring days.", + 'GAUSS_50311': "[GAUSS-50311] : Failed to change password for %s.", + 'GAUSS_50312': "[GAUSS-50312] : There are other users in the group %s " + "on %s, skip to delete group.", + 'GAUSS_50313': "[GAUSS-50313] : Failed to delete %s group.", + 'GAUSS_50314': "[GAUSS-50314] : Failed to delete %s user.", + 'GAUSS_50315': "[GAUSS-50315] : The user %s is not matched with the " + "owner of %s.", + 'GAUSS_50316': "[GAUSS-50316] : Group [%s] does not exist.", + 'GAUSS_50317': "[GAUSS-50317] : Failed to check user and password.", + 'GAUSS_50318': "[GAUSS-50318] : Failed to add %s user.", + 'GAUSS_50319': "[GAUSS-50319] : Failed to add %s group.", + 'GAUSS_50320': "[GAUSS-50320] : Failed to set '%s' to '%s' in " + "/etc/ssh/sshd_config.", + 'GAUSS_50321': "[GAUSS-50321] : Failed to get configuration of '%s' " + "from /etc/ssh/sshd_config.", + 'GAUSS_50322': "[GAUSS-50322] : Failed to encrypt the password for %s", + 'GAUSS_50323': "[GAUSS-50323] : The user %s is not the cluster " + "installation user " + } + + ########################################################################### + # disk + ########################################################################### + GAUSS_504 = { + 'GAUSS_50400': "[GAUSS-50400] : The remaining space of device [%s] " + "cannot be less than %s.", + 'GAUSS_50401': "[GAUSS-50401] : The usage of the device [%s] space " + "cannot be greater than %s.", + 'GAUSS_50402': "[GAUSS-50402] : The usage of INODE cannot be greater " + "than %s.", + 'GAUSS_50403': "[GAUSS-50403] : The IO scheduling policy is " + "incorrect.", + 'GAUSS_50404': "[GAUSS-50404] : The XFS mount type must be %s.", + 'GAUSS_50405': "[GAUSS-50405] : The pre-read block size must " + "be 16384.", + 'GAUSS_50406': "[GAUSS-50406] : Failed to obtain disk read and " + "write rates.", + 'GAUSS_50407': "[GAUSS-50407] : Failed to clean shared semaphore.", + 'GAUSS_50408': "[GAUSS-50408] : Failed to obtain disk read-ahead " + "memory block.", + 'GAUSS_50409': "[GAUSS-50409] : The remaining space of dns cannot " + "support shrink.", + 'GAUSS_50410': "[GAUSS-50410] : Failed to check if remaining space " + "of dns support shrink.", + 'GAUSS_50411': "[GAUSS-50411] : The remaining space cannot be less " + "than %s.", + 'GAUSS_50412': "[GAUSS-50412] : Failed to get disk space of database " + "node %s.", + 'GAUSS_50413': "[GAUSS-50413] : Failed to analysis" + " the disk information." + + } + + ########################################################################### + # memory + ########################################################################### + GAUSS_505 = { + 'GAUSS_50500': "[GAUSS-50500] : The SWAP partition is smaller than " + "the actual memory.", + 'GAUSS_50501': "[GAUSS-50501] : Shared_buffers must be less than " + "shmmax. Please check it.", + 'GAUSS_50502': "[GAUSS-50502] : Failed to obtain %s information." + } + + ########################################################################### + # network + ########################################################################### + GAUSS_506 = { + 'GAUSS_50600': "[GAUSS-50600] : The IP address cannot be pinged, " + "which is caused by network faults.", + 'GAUSS_50601': "[GAUSS-50601] : The port [%s] is occupied or the ip " + "address is incorrectly configured.", + 'GAUSS_50602': "[GAUSS-50602] : Failed to bind network adapters.", + 'GAUSS_50603': "[GAUSS-50603] : The IP address is invalid.", + 'GAUSS_50604': "[GAUSS-50604] : Failed to obtain network interface " + "card of backIp(%s).", + 'GAUSS_50605': "[GAUSS-50605] : Failed to obtain back IP subnet mask.", + 'GAUSS_50606': "[GAUSS-50606] : Back IP(s) do not have the same " + "subnet mask.", + 'GAUSS_50607': "[GAUSS-50607] : Failed to obtain configuring virtual " + "IP line number position of network startup file.", + 'GAUSS_50608': "[GAUSS-50608] : Failed to writing virtual IP setting " + "cmds into init file.", + 'GAUSS_50609': "[GAUSS-50609] : Failed to check port: %s.", + 'GAUSS_50610': "[GAUSS-50610] : Failed to get the range of " + "random port.", + 'GAUSS_50611': "[GAUSS-50611] : Failed to obtain network card " + "bonding information.", + 'GAUSS_50612': "[GAUSS-50612] : Failed to obtain network card %s " + "value.", + 'GAUSS_50613': "[GAUSS-50613] : Failed to set network card %s value.", + 'GAUSS_50614': "[GAUSS-50614] : Failed to check network information.", + 'GAUSS_50615': "[GAUSS-50615] : IP %s and IP %s are not in the " + "same network segment.", + 'GAUSS_50616': "[GAUSS-50616] : Failed to get network interface.", + 'GAUSS_50617': "[GAUSS-50617] : The node of XML configure file " + "has the same virtual IP.", + 'GAUSS_50618': "[GAUSS-50618] : %s. The startup file for SUSE OS" + " is /etc/init.d/boot.local. The startup file for " + "Redhat OS is /etc/rc.d/rc.local.", + 'GAUSS_50619': "[GAUSS-50619] : Failed to obtain network" + " card information.", + 'GAUSS_50620': "[GAUSS-50620] : Failed to check network" + " RX drop percentage.", + 'GAUSS_50621': "[GAUSS-50621] : Failed to check network care speed.\n", + 'GAUSS_50622': "[GAUSS-50622] : Failed to obtain network card " + "interrupt count numbers. Commands for getting " + "interrupt count numbers: %s." + + } + + ########################################################################### + # firwall + ########################################################################### + GAUSS_507 = { + 'GAUSS_50700': "[GAUSS-50700] : The firewall should be disabled.", + 'GAUSS_50701': "[GAUSS-50701] : The firewall should be opened." + } + + ########################################################################### + # crontab + ########################################################################### + GAUSS_508 = { + 'GAUSS_50800': "[GAUSS-50800] : Regular tasks are not started.", + 'GAUSS_50801': "[GAUSS-50801] : Failed to set up crontab.", + 'GAUSS_50802': "[GAUSS-50802] : Failed to %s service.", + 'GAUSS_50803': "[GAUSS-50803] : Failed to check user cron.", + 'GAUSS_50804': "[GAUSS-50804] : Failed to obtain user crontab list." + } + + ########################################################################### + # Clock service + ########################################################################### + GAUSS_509 = { + 'GAUSS_50900': "[GAUSS-50900] : The NTPD service is not installed.", + 'GAUSS_50901': "[GAUSS-50901] : The NTPD service is not started.", + 'GAUSS_50902': "[GAUSS-50902] : The system time is different." + } + + ########################################################################### + # THP + ########################################################################### + GAUSS_510 = { + 'GAUSS_51000': "[GAUSS-51000] : THP services must be shut down.", + 'GAUSS_51001': "[GAUSS-51001] : Failed to obtain THP service.", + 'GAUSS_51002': "[GAUSS-51002] : Failed to close THP service.", + 'GAUSS_51003': "[GAUSS-51003] : Failed to set session process." + } + + ########################################################################### + # SSH trust + ########################################################################### + GAUSS_511 = { + 'GAUSS_51100': "[GAUSS-51100] : Failed to verify SSH trust on " + "these nodes: %s.", + 'GAUSS_51101': "[GAUSS-51101] : SSH exception: \n%s", + 'GAUSS_51102': "[GAUSS-51102] : Failed to exchange SSH keys " + "for user [%s] performing the %s operation.", + 'GAUSS_51103': "[GAUSS-51103] : Failed to execute the PSSH " + "command [%s].", + 'GAUSS_51104': "[GAUSS-51104] : Failed to obtain SSH status.", + 'GAUSS_51105': "[GAUSS-51105] : Failed to parse SSH output: %s.", + 'GAUSS_51106': "[GAUSS-51106] : The SSH tool does not exist.", + 'GAUSS_51107': "[GAUSS-51107] : Ssh Paramiko failed.", + 'GAUSS_51108': "[GAUSS-51108] : Ssh-keygen failed.", + 'GAUSS_51109': "[GAUSS-51109] : Failed to check authentication.", + 'GAUSS_51110': "[GAUSS-51110] : Failed to obtain RSA host key " + "for local host.", + 'GAUSS_51111': "[GAUSS-51111] : Failed to append local ID to " + "authorized_keys on remote node.", + 'GAUSS_51112': "[GAUSS-51112] : Failed to exchange SSH keys " + "for user[%s] using hostname.", + 'GAUSS_51113': "[GAUSS-51113] : Failed to generate passphrase keyword." + } + + ########################################################################### + # cluster/XML configruation + ########################################################################### + GAUSS_512 = { + 'GAUSS_51200': "[GAUSS-51200] : The parameter [%s] in the XML " + "file does not exist.", + 'GAUSS_51201': "[GAUSS-51201] : Node names must be configured.", + 'GAUSS_51202': "[GAUSS-51202] : Failed to add the %s instance.", + 'GAUSS_51203': "[GAUSS-51203] : Failed to obtain the %s " + "information from static configuration files.", + 'GAUSS_51204': "[GAUSS-51204] : Invalid %s instance type: %d.", + 'GAUSS_51205': "[GAUSS-51205] : Failed to refresh the %s instance ID.", + 'GAUSS_51206': "[GAUSS-51206] : The MPPRC file path must " + "be an absolute path: %s.", + 'GAUSS_51207': "[GAUSS-51207] : Failed to obtain backIp " + "from node [%s].", + 'GAUSS_51208': "[GAUSS-51208] : Invalid %s number [%d].", + 'GAUSS_51209': "[GAUSS-51209] : Failed to obtain %s " + "configuration on the host [%s].", + 'GAUSS_51210': "[GAUSS-51210] : The obtained number does " + "not match the instance number.", + 'GAUSS_51211': "[GAUSS-51211] : Failed to save a static " + "configuration file.", + 'GAUSS_51212': "[GAUSS-51212] : There is no information about %s.", + 'GAUSS_51213': "[GAUSS-51213] : The port number of XML [%s] " + "conflicted.", + 'GAUSS_51214': "[GAUSS-51214] : The number of capacity expansion " + "database nodes cannot be less than three", + 'GAUSS_51215': "[GAUSS-51215] : The capacity expansion node [%s] " + "cannot contain GTM/CM/ETCD.", + 'GAUSS_51216': "[GAUSS-51216] : The capacity expansion node [%s] " + "must contain CN or DN.", + 'GAUSS_51217': "[GAUSS-51217] : The cluster's static configuration " + "does not match the new configuration file.", + 'GAUSS_51218': "[GAUSS-51218] : Failed to obtain initialized " + "configuration parameter: %s.", + 'GAUSS_51219': "[GAUSS-51219] : There is no CN in cluster.", + 'GAUSS_51220': "[GAUSS-51220] : The IP address %s is incorrect.", + 'GAUSS_51221': "[GAUSS-51221] : Failed to configure hosts " + "mapping information.", + 'GAUSS_51222': "[GAUSS-51222] : Failed to check hostname mapping.", + 'GAUSS_51223': "[GAUSS-51223] : Failed to obtain network " + "inet addr on the node(%s).", + 'GAUSS_51224': "[GAUSS-51224] : The ip(%s) has been used " + "on other nodes.", + 'GAUSS_51225': "[GAUSS-51225] : Failed to set virtual IP.", + 'GAUSS_51226': "[GAUSS-51226] : Virtual IP(s) and Back IP(s) " + "do not have the same network segment.", + 'GAUSS_51227': "[GAUSS-51227] : The number of %s on all nodes " + "are different.", + 'GAUSS_51228': "[GAUSS-51228] : The number %s does not " + "match %s number.", + 'GAUSS_51229': "[GAUSS-51229] : The database node listenIp(%s) is not " + "in the virtualIp or backIp on the node(%s).", + 'GAUSS_51230': "[GAUSS-51230] : The number of %s must %s.", + 'GAUSS_51231': "[GAUSS-51231] : Old nodes is less than 2.", + 'GAUSS_51232': "[GAUSS-51232] : XML configuration and static " + "configuration are the same.", + 'GAUSS_51233': "[GAUSS-51233] : The Port(%s) is invalid " + "on the node(%s).", + 'GAUSS_51234': "[GAUSS-51234] : The configuration file [%s] " + "contains parsing errors.", + 'GAUSS_51235': "[GAUSS-51235] : Invalid directory [%s].", + 'GAUSS_51236': "[GAUSS-51236] : Failed to parsing xml.", + 'GAUSS_51239': "[GAUSS-51239] : Failed to parse json. gs_collect " + "configuration file (%s) is invalid , " + "check key in json file", + 'GAUSS_51240': "[GAUSS-51240] : gs_collect configuration file " + "is invalid, TypeName or content must in config file.", + 'GAUSS_51241': "[GAUSS-51241] : The parameter %s(%s) formate " + "is wrong, or value is less than 0.", + 'GAUSS_51242': "[GAUSS-51242] : gs_collect configuration file " + "is invalid: %s, the key: (%s) is invalid.", + 'GAUSS_51243': "[GAUSS-51243] : content(%s) does not match the " + "typename(%s) in gs_collect configuration file(%s).", + 'GAUSS_51244': "[GAUSS-51244] : (%s) doesn't yet support.", + 'GAUSS_51245': "[GAUSS-51245] : There are duplicate key(%s).", + 'GAUSS_51246': "[GAUSS-51246] : %s info only support " + "one time collect.", + 'GAUSS_51247': "[GAUSS-51247] : These virtual IP(%s) are not " + "accessible after configuring.", + 'GAUSS_51248': "[GAUSS-51248] : The hostname(%s) may be not same with " + "hostname(/etc/hostname)", + 'GAUSS_51249': "[GAUSS-51249] : There is no database node instance " + "in the current node.", + 'GAUSS_51250': "[GAUSS-51250] : Error: the '%s' is illegal.\nthe path " + "name or file name should be letters, number or -_:.", + 'GAUSS_51251': "[GAUSS-51251] : The %s cannot be a root user group or a link." + + + } + + ########################################################################### + # SQL exception + ########################################################################### + GAUSS_513 = { + 'GAUSS_51300': "[GAUSS-51300] : Failed to execute SQL: %s.", + 'GAUSS_51301': "[GAUSS-51301] : Execute SQL time out. \nSql: %s.", + 'GAUSS_51302': "[GAUSS-51302] : The table '%s.%s' does not exist " + "or is private table!", + 'GAUSS_51303': "[GAUSS-51303] : Query '%s' has no record!.", + 'GAUSS_51304': "[GAUSS-51304] : Query '%s' result '%s' is incorrect!.", + 'GAUSS_51305': "[GAUSS-51305] : The table '%s.%s' exists!", + 'GAUSS_51306': "[GAUSS-51306] : %s: Abnormal reason:%s", + 'GAUSS_51307': "[GAUSS-51307] : Error: can not get sql execute " + "status.", + 'GAUSS_51308': "[GAUSS-51308] : Error: can not load result data.", + 'GAUSS_51309': "[GAUSS-51309] : Can not get correct result" + " by executing sql: %s", + 'GAUSS_51310': "[GAUSS-51310] : Failed to get connection" + " with database %s" + + } + + ########################################################################### + # Shell exception + ########################################################################### + GAUSS_514 = { + 'GAUSS_51400': "[GAUSS-51400] : Failed to execute the command: %s.", + 'GAUSS_51401': "[GAUSS-51401] : Failed to do %s.sh.", + 'GAUSS_51402': "[GAUSS-51402]: Failed to generate certs.", + 'GAUSS_51403': "[GAUSS-51403]: commond execute failure," + " check %s failed!", + 'GAUSS_51404': "[GAUSS-51404] : Not supported command %s.", + 'GAUSS_51405': "[GAUSS-51405] : You need to install software:%s\n" + + } + + ########################################################################### + # interface calls exception + ########################################################################### + GAUSS_515 = { + 'GAUSS_51500': "[GAUSS-51500] : Failed to call the interface %s. " + "Exception: %s." + } + + ########################################################################### + # cluster/instance status + ########################################################################### + GAUSS_516 = { + 'GAUSS_51600': "[GAUSS-51600] : Failed to obtain the cluster status.", + 'GAUSS_51601': "[GAUSS-51601] : Failed to check %s status.", + 'GAUSS_51602': "[GAUSS-51602] : The cluster status is Abnormal.", + 'GAUSS_51603': "[GAUSS-51603] : Failed to obtain peer %s instance.", + 'GAUSS_51604': "[GAUSS-51604] : There is no HA status for %s.", + 'GAUSS_51605': "[GAUSS-51605] : Failed to check whether " + "the %s process exists.", + 'GAUSS_51606': "[GAUSS-51606] : Failed to kill the %s process.", + 'GAUSS_51607': "[GAUSS-51607] : Failed to start %s.", + 'GAUSS_51608': "[GAUSS-51608] : Failed to lock cluster", + 'GAUSS_51609': "[GAUSS-51609] : Failed to unlock cluster", + 'GAUSS_51610': "[GAUSS-51610] : Failed to stop %s.", + 'GAUSS_51611': "[GAUSS-51611] : Failed to create %s instance.", + 'GAUSS_51612': "[GAUSS-51612] : The node id [%u] are not found " + "in the cluster.", + 'GAUSS_51613': "[GAUSS-51613] : There is no instance in %s to " + "be built.", + 'GAUSS_51614': "[GAUSS-51614] : Received signal[%d].", + 'GAUSS_51615': "[GAUSS-51615] : Failed to initialize instance.", + 'GAUSS_51616': "[GAUSS-51616] : Failed to dump %s schema.", + 'GAUSS_51617': "[GAUSS-51617] : Failed to rebuild %s.", + 'GAUSS_51618': "[GAUSS-51618] : Failed to get all hostname.", + 'GAUSS_51619': "[GAUSS-51619] : The host name [%s] is not " + "in the cluster.", + 'GAUSS_51620': "[GAUSS-51620] : Failed to obtain %s " + "instance information.", + 'GAUSS_51621': "[GAUSS-51621] : HA IP is empty.", + 'GAUSS_51622': "[GAUSS-51622] : There is no %s on %s node.", + 'GAUSS_51623': "[GAUSS-51623] : Failed to obtain version.", + 'GAUSS_51624': "[GAUSS-51624] : Failed to get DN connections.", + 'GAUSS_51625': "[GAUSS-51625] : Cluster is running.", + 'GAUSS_51626': "[GAUSS-51626] : Failed to rollback.", + 'GAUSS_51627': "[GAUSS-51627] : Configuration failed.", + 'GAUSS_51628': "[GAUSS-51628] : The version number of new cluster " + "is [%s]. It should be float.", + 'GAUSS_51629': "[GAUSS-51629] : The version number of new cluster " + "is [%s]. It should be greater than or equal to " + "the old version.", + 'GAUSS_51630': "[GAUSS-51630] : No node named %s.", + 'GAUSS_51631': "[GAUSS-51631] : Failed to delete the %s instance.", + 'GAUSS_51632': "[GAUSS-51632] : Failed to do %s.", + 'GAUSS_51633': "[GAUSS-51633] : The step of upgrade " + "number %s is incorrect.", + 'GAUSS_51634': "[GAUSS-51634] : Waiting node synchronizing timeout " + "lead to failure.", + 'GAUSS_51635': "[GAUSS-51635] : Failed to check SHA256.", + 'GAUSS_51636': "[GAUSS-51636] : Failed to obtain %s node information.", + 'GAUSS_51637': "[GAUSS-51637] : The %s does not match with %s.", + 'GAUSS_51638': "[GAUSS-51638] : Failed to append instance on " + "host [%s].", + 'GAUSS_51639': "[GAUSS-51639] : Failed to obtain %s status of " + "local node.", + 'GAUSS_51640': "[GAUSS-51640] : Can't connect to cm_server, cluster " + "is not running possibly.", + 'GAUSS_51641': "[GAUSS-51641] : Cluster redistributing status is not " + "accord with expectation.", + 'GAUSS_51642': "[GAUSS-51642] : Failed to promote peer instances.", + 'GAUSS_51643': "[GAUSS-51643] : Cluster is in read-only mode.", + 'GAUSS_51644': "[GAUSS-51644] : Failed to set resource control " + "for the cluster.", + 'GAUSS_51645': "[GAUSS-51645] : Failed to restart %s.", + 'GAUSS_51646': "[GAUSS-51646] : The other OM operation is currently " + "being performed in the cluster node:" + " '%s'.", + 'GAUSS_51647': "[GAUSS-51647] : The operation step of OM components " + "in current cluster nodes do not match" + " with each other: %s.", + 'GAUSS_51648': "[GAUSS-51648] : Waiting for redistribution process " + "to end timeout.", + 'GAUSS_51649': "[GAUSS-51649] : Capture exceptions '%s' : %s.", + 'GAUSS_51650': "[GAUSS-51650] : Unclassified exceptions: %s.", + 'GAUSS_51651': "[GAUSS-51651] : The node '%s' status is Abnormal.\n" + "It is required that all the nodes should be normal " + "except the target ones.\nPlease add this node in the" + " list after -h if it is also a target one.", + 'GAUSS_51652': "[GAUSS-51652] : Failed to get cluster node " + "info.exception is: %s.", + 'GAUSS_51653': "[GAUSS-51653] : No database objects " + "were found in the cluster!", + 'GAUSS_51654': "[GAUSS-51654] : Cannot query instance process" + " version from function.", + 'GAUSS_51655': "[GAUSS-51655] : There is %s on the cluster when operating on a cluster" + "the %s parameter is not needed." + + } + + ########################################################################### + # Check system table + ########################################################################### + GAUSS_517 = { + 'GAUSS_51700': "[GAUSS-51700] : There must be only one record in the " + "pgxc_group table.", + 'GAUSS_51701': "[GAUSS-51701] : The current node group is incorrect.", + 'GAUSS_51702': "[GAUSS-51702] : Failed to obtain node group " + "information.", + 'GAUSS_51703': "[GAUSS-51703] : Failed to drop record from " + "PGXC_NODE.", + 'GAUSS_51704': "[GAUSS-51704] : Failed to set Cgroup.", + 'GAUSS_51705': "[GAUSS-51705] : Failed to update PGXC_NODE.", + 'GAUSS_51706': "[GAUSS-51706] : Failed to check Cgroup.", + 'GAUSS_51707': "[GAUSS-51707] : Failed to install Cgroup.", + 'GAUSS_51708': "[GAUSS-51708] : Failed to uninstall Cgroup.", + 'GAUSS_51709': "[GAUSS-51709] : Failed to clean Cgroup " + "configuration file." + } + + ########################################################################### + # environmental variable + ########################################################################### + GAUSS_518 = { + 'GAUSS_51800': "[GAUSS-51800] : The environmental variable %s is " + "empty. or variable has exceeded maximum length", + 'GAUSS_51801': "[GAUSS-51801] : The environment variable %s exists.", + 'GAUSS_51802': "[GAUSS-51802] : Failed to obtain the environment " + "variable %s.", + 'GAUSS_51803': "[GAUSS-51803] : Failed to delete the environment " + "variable %s.", + 'GAUSS_51804': "[GAUSS-51804] : Failed to set the environment " + "variable %s.", + 'GAUSS_51805': "[GAUSS-51805] : The environmental variable [%s]'s " + "value is invalid.", + 'GAUSS_51806': "[GAUSS-51806] : The cluster has been installed.", + 'GAUSS_51807': "[GAUSS-51807] : $GAUSSHOME of user is not equal to " + "installation path.", + 'GAUSS_51808': "[GAUSS-51808] : The env file contains errmsg: %s." + } + + ########################################################################### + # OS version + ########################################################################### + GAUSS_519 = { + 'GAUSS_51900': "[GAUSS-51900] : The current OS is not supported.", + 'GAUSS_51901': "[GAUSS-51901] : The OS versions are different " + "among cluster nodes." + } + + ########################################################################### + # database version + ########################################################################### + GAUSS_520 = { + 'GAUSS_52000': "[GAUSS-52000] : Failed to obtain time zone " + "information about the cluster node.", + 'GAUSS_52001': "[GAUSS-52001] : Time zone information is " + "different among cluster nodes." + } + + ########################################################################### + # OS time zone + ########################################################################### + GAUSS_521 = { + 'GAUSS_52100': "[GAUSS-52100] : Failed to obtain cluster node " + "character sets.", + 'GAUSS_52101': "[GAUSS-52101] : Character sets are different " + "among cluster nodes.", + 'GAUSS_52102': "[GAUSS-52102] : The parameter [%s] value is not equal " + "to the expected value.", + 'GAUSS_52103': "[GAUSS-52103] : Failed to forcibly make the character " + "sets to take effect." + } + + ########################################################################### + # OS character set + ########################################################################### + GAUSS_522 = { + 'GAUSS_52200': "[GAUSS-52200] : Unable to import module: %s.", + 'GAUSS_52201': "[GAUSS-52201] : The current python version %s " + "is not supported." + } + + ########################################################################### + # Operating system parameters + ########################################################################### + GAUSS_523 = { + 'GAUSS_52300': "[GAUSS-52300] : Failed to set OS parameters.", + 'GAUSS_52301': "[GAUSS-52301] : Failed to check OS parameters." + + } + + ########################################################################### + # preinsatll install + ########################################################################### + GAUSS_524 = { + 'GAUSS_52400': "[GAUSS-52400] : Installation environment does not " + "meet the desired result.", + 'GAUSS_52401': "[GAUSS-52401] : On systemwide basis, the maximum " + "number of %s is not correct. the current %s value is:", + 'GAUSS_52402': "[GAUSS-52402] : IP [%s] is not matched " + "with hostname [%s]. \n", + 'GAUSS_52403': "[GAUSS-52403] : Command \"%s\" does not exist or the " + "user has no execute permission on %s." + } + + ########################################################################### + # uninsatll postuninstall + ########################################################################### + GAUSS_525 = { + 'GAUSS_52500': "[GAUSS-52500] : Failed to delete regular tasks.", + 'GAUSS_52501': "[GAUSS-52501] : Run %s script before " + "executing this script.", + 'GAUSS_52502': "[GAUSS-52502] : Another OM process is being executed. " + "To avoid conflicts, this process ends in advance." + } + + ########################################################################### + # expand and shrik + ########################################################################### + GAUSS_526 = { + 'GAUSS_52600': "[GAUSS-52600] : Can not obtain any cluster ring.", + 'GAUSS_52601': "[GAUSS-52601] : Redistribution failed due to" + " user request.", + 'GAUSS_52602': "[GAUSS-52602] : There is no CN in old nodes.", + 'GAUSS_52603': "[GAUSS-52603] : There is no CN on the contraction of " + "the remaining nodes.", + 'GAUSS_52604': "[GAUSS-52604] : Parameter '-r'[%s] can not be " + "more than the numbers of cluster ring[%s].", + 'GAUSS_52605': "[GAUSS-52605] : Can not contract local node(%s).", + 'GAUSS_52606': "[GAUSS-52606] : Contract too many nodes. " + "It should left three nodes to format " + "a cluster at least.", + 'GAUSS_52607': "[GAUSS-52607] : [%s] does not at the " + "end of instance list.", + 'GAUSS_52608': "[GAUSS-52608] : [%s] contains %s instance.", + 'GAUSS_52609': "[GAUSS-52609] : All contracted nodes do not " + "contain database node instance.", + 'GAUSS_52610': "[GAUSS-52610] : The current node group are " + "node group after contraction.", + 'GAUSS_52611': "[GAUSS-52611] : There must be only one record " + "in the current node group.", + 'GAUSS_52612': "[GAUSS-52612] : All dilatation nodes do not contain " + "the database node instance.", + 'GAUSS_52613': "[GAUSS-52613] : Static configuration is not matched " + "on some nodes. Please handle it first.", + 'GAUSS_52614': "[GAUSS-52614] : Timeout. The current " + "cluster status is %s.", + 'GAUSS_52615': "[GAUSS-52615] : Cluster lock unlocked due to timeout.", + 'GAUSS_52616': "[GAUSS-52616] : Can not find a similar " + "instance for [%s %s].", + 'GAUSS_52617': "[GAUSS-52617] : Invalid check type.", + 'GAUSS_52618': "[GAUSS-52618] : Failed to delete etcd from node.", + 'GAUSS_52619': "[GAUSS-52619] : Failed to uninstall application.", + 'GAUSS_52620': "[GAUSS-52620] : Not all nodes found. The following " + "is what we found: %s.", + 'GAUSS_52621': "[GAUSS-52621] : No DNs specified in target " + "create new group.", + 'GAUSS_52622': "[GAUSS-52622] : No new group name specified in " + "target create new group.", + 'GAUSS_52623': "[GAUSS-52623] : Failed to check node group " + "numbers: Node group numbers is [%d].", + 'GAUSS_52624': "[GAUSS-52624] : Failed to check %s node " + "group members: Invaild group name or nodes.", + 'GAUSS_52625': "[GAUSS-52625] : The local instance and peer instance " + "does not both in contracted nodes.", + 'GAUSS_52626': "[GAUSS-52626] : The CN connection on the old " + "nodes are abnormal.", + 'GAUSS_52627': "[GAUSS-52627] : The current cluster is locked.", + 'GAUSS_52628': "[GAUSS-52628] : Static configuration has already " + "been updated on all nodes, expansion has been " + "completed possibly.", + 'GAUSS_52629': "[GAUSS-52629] : Cluster ring(%s) can not obtain " + "less than three nodes.", + 'GAUSS_52630': "[GAUSS-52630] : Failed to set the read-only mode " + "parameter for all database node instances.", + 'GAUSS_52631': "[GAUSS-52631] : Invalid value for GUC parameter " + "comm_max_datanode: %s.", + 'GAUSS_52632': "[GAUSS-52632] : Cluster breakdown or " + "abnormal operation during " + "expanding online, lock process for expansion is lost.", + 'GAUSS_52633': "[GAUSS-52633] : Can not excute redistribution " + "for shrink excuted failed." + + + } + + ########################################################################### + # replace + ########################################################################### + GAUSS_527 = { + 'GAUSS_52700': "[GAUSS-52700] : Failed to update ETCD.", + 'GAUSS_52701': "[GAUSS-52701] : All the CMAgents instances are " + "abnormal. Cannot fix the cluster.", + 'GAUSS_52702': "[GAUSS-52702] : The cluster status is Normal. " + "There is no instance to fix.", + 'GAUSS_52703': "[GAUSS-52703] : The number of normal ETCD must " + "be greater than half.", + 'GAUSS_52704': "[GAUSS-52704] : Failed to check the %s condition.", + 'GAUSS_52705': "[GAUSS-52705] : Failed to obtain ETCD key.", + 'GAUSS_52706': "[GAUSS-52706] : Failed to clean ETCD and touch " + "flag file on %s.", + 'GAUSS_52707': "[GAUSS-52707] : Failed to install on %s.", + 'GAUSS_52708': "[GAUSS-52708] : Failed to configure on %s.", + 'GAUSS_52709': "[GAUSS-52709] : Failed to check the cluster " + "configuration differences:", + 'GAUSS_52710': "[GAUSS-52710] : Replacement failed.", + 'GAUSS_52711': "[GAUSS-52711] : Failed to set CMAgent start mode." + } + + ########################################################################### + # manageCN and changeIP + ########################################################################### + GAUSS_528 = { + 'GAUSS_52800': "[GAUSS-52800] : Cluster is %s(%s) now.", + 'GAUSS_52801': "[GAUSS-52801] : Only allow to %s one CN. The %s " + "is not matched.", + 'GAUSS_52802': "[GAUSS-52802] : Only allow to add one CN at the end.", + 'GAUSS_52803': "[GAUSS-52803] : There is at least one Normal " + "CN after delete CN.", + 'GAUSS_52804': "[GAUSS-52804] : Failed to add the Abnormal CN.", + 'GAUSS_52805': "[GAUSS-52805] : Failed to find another instance as " + "model for instance(%s).", + 'GAUSS_52806': "[GAUSS-52806] : Invalid rollback step: %s.", + 'GAUSS_52807': "[GAUSS-52807] : There is no IP changed.", + 'GAUSS_52808': "[GAUSS-52808] : Detected CN %s, but the action is %s.", + 'GAUSS_52809': "[GAUSS-52809] : Only allow to add or delete one CN.", + 'GAUSS_52810': "[GAUSS-52810] : There is Abnormal coodinator(s) " + "in cluster, please delete it firstly." + } + + ########################################################################### + # upgrade + ########################################################################### + GAUSS_529 = { + 'GAUSS_52900': "[GAUSS-52900] : Failed to upgrade strategy: %s.", + 'GAUSS_52901': "[GAUSS-52901] : New cluster commitid cannot be same " + "with old cluster commitid.", + 'GAUSS_52902': "[GAUSS-52902] : Can not support upgrade from %s to %s", + 'GAUSS_52903': "[GAUSS-52903] : The new cluster version number[%s] " + "should be bigger than the old cluster[%s].", + 'GAUSS_52904': "[GAUSS-52904] : Please choose right upgrade strategy.", + 'GAUSS_52905': "[GAUSS-52905] : Upgrade nodes number cannot " + "be more than %d.", + 'GAUSS_52906': "[GAUSS-52906] : Grey upgrade nodes number cannot " + "be more than cluster nodes.", + 'GAUSS_52907': "[GAUSS-52907] : Failed to cancel the cluster " + "read-only mode", + 'GAUSS_52908': "[GAUSS-52908] : Failed to set cluster read-only mode.", + 'GAUSS_52909': "[GAUSS-52909] : Specified upgrade nodes with " + "same step can do upgrade task.", + 'GAUSS_52910': "[GAUSS-52910] : These nodes %s have been successfully " + "upgraded to new version, no need to upgrade again.", + 'GAUSS_52911': "[GAUSS-52911] : Last unsuccessfully upgrade nodes " + "%s are not same with current upgrade nodes.", + 'GAUSS_52912': "[GAUSS-52912] : All nodes have been upgraded, so " + "cannot use --continue.", + 'GAUSS_52913': "[GAUSS-52913] : All nodes have been upgraded. " + "No need to use --continue.", + 'GAUSS_52914': "[GAUSS-52914] : The record commitid is not same " + "with current commitid.", + 'GAUSS_52915': "[GAUSS-52915] : $GAUSSHOME is not a symbolic link.", + 'GAUSS_52916': "[GAUSS-52916] : Current upgrade status is " + "not pre commit.", + 'GAUSS_52917': "[GAUSS-52917] : Failed to drop old pmk schema.", + 'GAUSS_52918': "[GAUSS-52918] : Failed to record node upgrade step " + "in table %s.%s.", + 'GAUSS_52919': "[GAUSS-52919] : Upgrade has already been committed " + "but not finished commit.", + 'GAUSS_52920': "[GAUSS-52920] : Can not use grey upgrade option " + "--continue before upgrade grey nodes.", + 'GAUSS_52921': "[GAUSS-52921] : Failed to query disk usage " + "with gs_check tool.", + 'GAUSS_52922': "[GAUSS-52922] : Disk usage exceeds %s, " + "please clean up before upgrading.", + 'GAUSS_52923': "[GAUSS-52923] : .", + 'GAUSS_52924': "[GAUSS-52924] : .", + 'GAUSS_52925': "[GAUSS-52925] : Input upgrade type [%s] is not same " + "with record upgrade type [%s].", + 'GAUSS_52926': "[GAUSS-52926] : The step of upgrade should be digit.", + 'GAUSS_52927': "[GAUSS-52927] : ", + 'GAUSS_52928': "[GAUSS-52928] : .", + 'GAUSS_52929': "[GAUSS-52929] : Failed to check application version. " + "Output: \n%s.", + 'GAUSS_52930': "[GAUSS-52930] : .", + 'GAUSS_52931': "[GAUSS-52931] : .", + 'GAUSS_52932': "[GAUSS-52932] : There is no CN in the remaining " + "old nodes.", + 'GAUSS_52933': "[GAUSS-52933] : There is not a majority of %s on the " + "remaining old nodes.", + 'GAUSS_52934': "[GAUSS-52934] : .", + 'GAUSS_52935': "[GAUSS-52935] : Current upgrade version is not same " + "with unfinished upgrade version record.", + 'GAUSS_52936': "[GAUSS-52936] : Upgrade is not finished, " + "cannot do another task.", + 'GAUSS_52937': "[GAUSS-52937] : Clean install directory option is " + "invalid, can only be 'new' or 'old'!", + 'GAUSS_52938': "[GAUSS-52938] : Can not find %s.", + 'GAUSS_52939': "[GAUSS-52939] : Can not get %s.", + 'GAUSS_52940': "[GAUSS-52940] : Invalid node type:%s.", + 'GAUSS_52941': "[GAUSS-52941] : Invalid node role:%s.", + 'GAUSS_52942': "[GAUSS-52942] : No such key to check guc value.", + 'GAUSS_52943': "[GAUSS-52943] : Invalid instance type:%s.", + 'GAUSS_52944': "[GAUSS-52944] : Not all nodes are upgraded." + + } + + ########################################################################### + # check + ########################################################################### + GAUSS_530 = { + 'GAUSS_53000': "[GAUSS-53000] : The database user [%s] is not " + "match with the old user [%s].", + 'GAUSS_53001': "[GAUSS-53001] : The result of query table " + "is incorrect: %s.", + 'GAUSS_53002': "[GAUSS-53002] : Failed to obtain SSD device.", + 'GAUSS_53003': "[GAUSS-53003] : The checked item does not meet " + "the standards.", + 'GAUSS_53004': "[GAUSS-53004] : Failed to collect statistics " + "on all nodes.", + 'GAUSS_53005': "[GAUSS-53005] : Unable to obtain SSD disk " + "on current node.", + 'GAUSS_53006': "[GAUSS-53006] : No database node instance uses data " + "directory %s on %s.", + 'GAUSS_53007': "[GAUSS-53007] : Failed to switch %s.", + 'GAUSS_53008': "[GAUSS-53008] : The current node do not install SSD. " + "Can not check SSD performance.", + 'GAUSS_53009': "[GAUSS-53009] : Failed to format cu of directory: %s.", + 'GAUSS_53010': "[GAUSS-53010] : The function name of %s is not exist " + "in the %s.", + 'GAUSS_53011': "[GAUSS-53011] : Failed to check %s.", + 'GAUSS_53012': "[GAUSS-53012] : Failed to insert pmk data to " + "database.", + 'GAUSS_53013': "[GAUSS-53013] : %s can not be empty.", + 'GAUSS_53014': "[GAUSS-53014] : %s must be a nonnegative integer.", + 'GAUSS_53015': "[GAUSS-53015] : The threshold Threshold_NG[%d] " + "must be greater than Threshold_Warning[%d].", + 'GAUSS_53016': "[GAUSS-53016] : The threshold Threshold_NG[%d] and " + "Threshold_Warning[%d] must be integer from 1 to 99.", + 'GAUSS_53017': "[GAUSS-53017] : Unsupported operating system %s.", + 'GAUSS_53018': "[GAUSS-53018] : Failed to get file handler " + "of process %s by use cmd %s.", + 'GAUSS_53019': "[GAUSS-53019] : Failed to delete variable '%s %s'" + " from /etc/sysctl.conf.", + 'GAUSS_53020': "[GAUSS-53020] : Failed to set %s.", + 'GAUSS_53021': "[GAUSS-53021] : %s only can be supported" + " on %s Platform.", + 'GAUSS_53022': "[GAUSS-53022] : Platform %s%s is not supported.", + 'GAUSS_53023': "[GAUSS-53023] : Failed to get CPUcores and MemSize." + " Error: %s", + 'GAUSS_53024': "[GAUSS-53024] : Failed to get ip string for" + " config pg_hba.conf.", + 'GAUSS_53025': "[GAUSS-53025] : content's type must be bytes.", + 'GAUSS_53026': "[GAUSS-53026] : bytes's type must be in (bytes, str).", + 'GAUSS_53027': "[GAUSS-53027] : content's len must >= (iv_len + 16).", + 'GAUSS_53028': "[GAUSS-53028] : Test PMK schema failed. " + "Output: \n%s", + 'GAUSS_53029': "[GAUSS-53029] : Failed to install pmk schema," + "Error: \n%s", + 'GAUSS_53030': "[GAUSS-53030] : The class must have %s", + 'GAUSS_53031': "[GAUSS-53031] : The cluster is None.", + 'GAUSS_53032': "[GAUSS-53032] : The speed limit must " + "be a nonnegative integer.", + 'GAUSS_53033': "[GAUSS-53033] : Invalid User : %s." + + } + + ########################################################################### + # check interface + ########################################################################### + GAUSS_531 = { + 'GAUSS_53100': "[GAUSS-53100] : [%s] is not supported in single " + "cluster.", + 'GAUSS_53101': "[GAUSS-53101] : This interface is not supported " + "in %s cluster.", + 'GAUSS_53102': "[GAUSS-53102] : [%s] is not supported in " + "express cluster.", + 'GAUSS_53103': "[GAUSS-53103] : The single primary multi standby " + "cluster does not support the product" + " version '%s'.", + 'GAUSS_53104': "[GAUSS-53104] : [%s] is not supported in " + "single instance cluster." + } + ########################################################################### + # Single Primary MultiStandby cluster + ########################################################################### + GAUSS_532 = { + 'GAUSS_53200': "[GAUSS-53200] : The number of standbys for each " + "database node instance must be the same. " + "Please set it.", + 'GAUSS_53201': "[GAUSS-53201] : The number of database node standbys " + "and the AZ settings are incorrect. Please set it.", + 'GAUSS_53202': "[GAUSS-53202] : The AZ information is incorrect. " + "Please set it.", + 'GAUSS_53203': "[GAUSS-53203] : The number of ETCD in %s. " + "Please set it.", + 'GAUSS_53204': "[GAUSS-53204] : [%s] is not supported in single " + "primary multistandby cluster.", + 'GAUSS_53205': "[GAUSS-53205] : The priority of %s must be higher " + "than %s. Please set it.", + 'GAUSS_53206': "[GAUSS-53206] : The value of %s must be greater " + "than 0 and less than 11. Please set it." + } + ########################################################################### + # License + ########################################################################### + GAUSS_533 = { + 'GAUSS_53300': "[GAUSS-53300] : The current product version '%s' " + "does not support the license " + "register/unregister operation.", + 'GAUSS_53301': "[GAUSS-53301] : The license control files are not " + "consistent on the cluster.", + 'GAUSS_53302': "[GAUSS-53302] : The current cluster does not apply " + "the license control, please upgrade it" + " first.", + 'GAUSS_53303': "[GAUSS-53303] : The DWS cluster does not support the " + "license register/unregister operation.", + 'GAUSS_53304': "[GAUSS-53304] : Can not register the enabled " + "features.", + 'GAUSS_53305': "[GAUSS-53304] : Can not un-register " + "the disabled features.", + 'GAUSS_53306': "[GAUSS-53306] : Can not register the unsupported " + "features of the product version '%s'.", + 'GAUSS_53307': "[GAUSS-53307] : No need to un-register the " + "unsupported " + "features of the product version '%s'." + } + ########################################################################### + # ROACH + # [GAUSS-53400] : Roach etcd operator failded + ########################################################################### + GAUSS_534 = { + 'GAUSS_53400': "[GAUSS-53400] : Roach ETCD term operate failed.", + 'GAUSS_53401': "[GAUSS-53401] : Roach delete/clean operate failed, " + "Failed to clean %s", + 'GAUSS_53402': "[GAUSS-53402] : Get %s cluster infomation/env " + "failed, %s", + 'GAUSS_53403': "[GAUSS-53403] : Cluster balance check failed", + 'GAUSS_53404': "[GAUSS-53404] : backup key %s does not exist" + } + ########################################################################## + # gs_collector + # [GAUSS-53500] : gs_collector failed + ########################################################################## + GAUSS_535 = { + 'GAUSS_53500': "[GAUSS-53500] : Relation %s does not exist.", + 'GAUSS_53501': "[GAUSS-53501] : Connect to server failed, " + "connection refused", + 'GAUSS_53502': "[GAUSS-53502] : Please check database status", + 'GAUSS_53503': "[GAUSS-53503] : There is no coordinator inst in " + "this host", + 'GAUSS_53504': "[GAUSS-53504] : There is no %s files: " + "please check start-time and end-time.", + 'GAUSS_53505': "[GAUSS-53505] : There is no log files: " + "please check cluster info.", + 'GAUSS_53506': "[GAUSS-53506] : Failed to mkdir.", + 'GAUSS_53507': "[GAUSS-53507] : Failed to execute %s command.", + 'GAUSS_53508': "[GAUSS-53508] : Core pattern is not core-e-p-t.", + 'GAUSS_53509': "[GAUSS-53509] : There is no core files: " + "please check core file name pattern.", + 'GAUSS_53510': "[GAUSS-53510] : Please check db status or " + "database name.", + 'GAUSS_53511': "[GAUSS-53511] : There is no %s process.", + 'GAUSS_53512': "[GAUSS-53512] : Gstack command not found.", + 'GAUSS_53513': "[GAUSS-53513] : Schema '%s' is not in white list.", + 'GAUSS_53514': "[GAUSS-53514] : Relation '%s' does not belong " + "to '%s' schema.", + 'GAUSS_53515': "[GAUSS-53515] : Database content '%s' is invalid, " + "only support 'schema.relation'.", + 'GAUSS_53516': "[GAUSS-53516] : There is no info should be collected ," + "gs_collector is finished. " + } + + GAUSS_536 = { + 'GAUSS_53600': "[GAUSS-53600]: Can not start the database, " + "the cmd is %s, Error:\n%s.", + 'GAUSS_53601': "[GAUSS-53601]: Can not start the primary database, " + "Error:\n%s.", + 'GAUSS_53602': "[GAUSS-53602]: Can not start the standby database, " + "Error:\n%s.", + 'GAUSS_53603': "[GAUSS-53603]: The dataDir can not be empty.", + 'GAUSS_53604': "[GAUSS_53604]: The hostName %s has not %s process.", + 'GAUSS_53605': "[GAUSS_53605]: The %s in hostName %s is running.", + 'GAUSS_53606': "[GAUSS-53606]: Can not stop the database, " + "the cmd is %s, Error:\n%s.", + 'GAUSS_53607': "[GAUSS-53607]: Fail to remove the file %s, " + "Error:\n%s.", + 'GAUSS_53608': "[GAUSS-53608]: Can not start the database, " + "Error:\n%s.", + 'GAUSS_53609': "[GAUSS-53609]: Can not stop the database, " + "Error:\n%s.", + 'GAUSS_53610': "[GAUSS-53610]: The input dataDir(%s) " + "may be incorrect.", + 'GAUSS_53611': "[GAUSS-53611]: Error information is :\n%s", + 'GAUSS_53612': "[GAUSS-53612]: Can not find any catalog in database %s" + } + + ########################################################################## + # gs_expansion + # [GAUSS-537] : gs_expansion failed + ########################################################################## + GAUSS_357 = { + "GAUSS_35700": "[GAUSS-35700] Expansion standby node failed.", + "GAUSS_35701": "[GAUSS-35701] Empty parameter. The %s parameter is" + "missing in the command.", + "GAUSS_35702": "[GAUSS-35702] Unrecognized parameter, standby host " + "backip %s is not in the " + "XML configuration file", + "GAUSS_35703": "[GAUSS-35703] Check standby database Failed. The " + "database on node is abnormal. \n" + "node [%s], user [%s], dataNode [%s]. \n" + "You can use command \"gs_ctl query -D %s\" for more " + "detail.", + "GAUSS_35704": "[GAUSS-35704] %s [%s] does not exist on node [%s].", + "GAUSS_35705": "[GAUSS-35705] Error, the database version is " + "inconsistent in %s: %s", + "GAUSS_35706": "[GAUSS-35706] Fail to %s on all new hosts.", + "GAUSS_35707": "[GAUSS-35707] Fail to check %s version on:\n%s", + "GAUSS_35708": "[GAUSS-35708] Inconsistent %s version with primary on \n%s", + "GAUSS_35709": "[GAUSS-35709] The %s of %s is not %s.", + "GAUSS_35710": "[GAUSS-35710] Generate static file [%s] not found.", + "GAUSS_35711": "[GAUSS-35711] %s in xml is not consistent with that in cluster.", + "GAUSS_35712": "[GAUSS-35712] User [%s] is not in the group [%s]." + } + + ########################################################################## + # gs_dropnode + # [GAUSS-358] : gs_dropnode failed + ########################################################################## + GAUSS_358 = { + "GAUSS_35800": "[GAUSS-35800] Expansion standby node failed.", + "GAUSS_35801": "[GAUSS-35801] Empty parameter. The %s parameter is " + "missing in the command.", + "GAUSS_35802": "[GAUSS-35802] The IP list of target node: %s" + "is not in the current cluster. Please check!", + "GAUSS_35803": "[GAUSS-35803] The IP of local host %s is in the " + "target node list. \n" + "Can not drop local host!\n", + "GAUSS_35804": "[GAUSS-35804] The dropnode operation can only be executed" + " at the primary node. \n ", + "GAUSS_35805": "[GAUSS-35805] Input %s. Operation aborted. ", + "GAUSS_35806": "[GAUSS-35806] Current status of cluster is %s .\n" + "It doesn't meet the requirement! ", + "GAUSS_35807": "[GAUSS-35807] The host %s which still exist in the " + "cluster can't be connected.\n" + "It doesn't meet the requirement!\nPlease add it to the " + "list of hosts to be dropped if it is a target host.", + "GAUSS_35808": "[GAUSS-35808] The %s is running switchover/failover!\n" + "The dropnode operation can only be executed when there is" + " no such operation!", + "GAUSS_35809": "[GAUSS-35809] Some important steps failed to execute. " + "Please refer to log for detail!", + "GAUSS_35810": "[GAUSS-35810] A same process is already running! ", + "GAUSS_35811": "[GAUSS-35811] In a cluster with the CM component, " + "the number of nodes must be greater than two to " + "perform the drop node operation. " + } diff --git a/tool/cm_tool/InstallImpl.py b/tool/cm_tool/InstallImpl.py new file mode 100644 index 0000000..f6c1f0c --- /dev/null +++ b/tool/cm_tool/InstallImpl.py @@ -0,0 +1,307 @@ +# -*- coding:utf-8 -*- +############################################################################# +# Copyright (c) 2022 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 : InstallImpl.py +############################################################################# + +import os +import re +import subprocess +import xml.etree.cElementTree as ETree +from ErrorCode import ErrorCode +from Common import executeCmdOnHost +from CMLog import CMLog + +class InstallImpl: + def __init__(self, install): + self.cmpkg = install.cmpkg + self.context = install + self.envFile = install.envFile + self.xmlFile = install.xmlFile + self.cmDirs = install.cmDirs + self.hostNames = install.hostNames + self.gaussHome = install.gaussHome + self.gaussLog = install.gaussLog + self.toolPath = install.toolPath + self.tmpPath = install.tmpPath + self.localhostName = install.localhostName + self.logger = install.logger + + def executeCmdOnHost(self, host, cmd, isLocal = False): + if host == self.localhostName: + isLocal = True + return executeCmdOnHost(host, cmd, isLocal) + + def prepareCMPath(self): + """ + create path: cmdir、cmdir/cm_server、cmdir/cm_agent + """ + self.logger.log("Preparing CM path.") + for (cmdir, host) in zip(self.cmDirs, self.hostNames): + cmd = "mkdir -p {cmdir}/cm_server {cmdir}/cm_agent".format(cmdir=cmdir) + status, output = self.executeCmdOnHost(host, cmd) + if status != 0: + self.logger.debug("Command: " + cmd) + errorDetail = "\nStatus: %s\nOutput: %s" % (status, output) + self.logger.logExit("Failed to create CM path." + errorDetail) + + def decompressCMPkg(self): + self.logger.log("Decompressing CM pacakage.") + if self.cmpkg == "": + return + # decompress cm pkg on localhost + decompressCmd = "tar -zxf %s -C %s" % (self.cmpkg, self.gaussHome) + status, output = subprocess.getstatusoutput(decompressCmd) + if status != 0: + self.logger.debug("Command: " + decompressCmd) + errorDetail = "\nStatus: %s\nOutput: %s" % (status, output) + self.logger.logExit("Failed to decompress cm pacakage to on localhost." + errorDetail) + + # If the version of CM pacakage is inconsistent with that of gaussdb, + # then exit. So no need to send CM pacakage to other nodes. + self.checkCMPkgVersion() + + # decompress cmpkg on other hosts + cmpkgName = os.path.basename(self.cmpkg) + for host in self.hostNames: + if host == self.localhostName: + continue + # copy cm pacakage to other hosts + scpCmd = "scp %s %s:%s" % (self.cmpkg, host, self.toolPath) + status, output = subprocess.getstatusoutput(scpCmd) + if status != 0: + self.logger.debug("Command: " + scpCmd) + errorDetail = "\nStatus: %s\nOutput: %s" % (status, output) + self.logger.logExit(("Failed to send cm pacakage to %s." % host) + errorDetail) + pkgPath = os.path.join(self.toolPath, cmpkgName) + decompressCmd = "tar -zxf %s -C %s" % (pkgPath, self.gaussHome) + status, output = self.executeCmdOnHost(host, decompressCmd) + if status != 0: + self.logger.debug("Command: " + decompressCmd) + errorDetail = "\nStatus: %s\nOutput: %s" % (status, output) + self.logger.logExit(("Failed to decompress cm pacakage to on host %s." % host) + errorDetail) + + def checkCMPkgVersion(self): + getCMVersionCmd = "source %s; cm_ctl -V" % self.envFile + status, output = subprocess.getstatusoutput(getCMVersionCmd) + if status != 0: + self.logger.logExit("Failed to get CM pacakage version.") + cmVersionList = re.findall(r'openGauss CM (\d.*\d) build', output) + if len(cmVersionList) == 0: + self.logger.logExit("Failed to get CM pacakage version.") + cmVersion = cmVersionList[0] + + getGaussdbVersionCmd = "source %s; gaussdb -V" % self.envFile + status, output = subprocess.getstatusoutput(getGaussdbVersionCmd) + if status != 0: + self.logger.logExit("Failed to get gaussdb version.") + gaussdbVersionList = re.findall(r'openGauss (\d.*\d) build', output) + if len(gaussdbVersionList) == 0: + self.logger.logExit("Failed to get gaussdb version.") + gaussdbVersion = gaussdbVersionList[0] + + if gaussdbVersion != cmVersion: + self.logger.logExit("The version of CM pacakage(%s) is inconsistent " + "with that of gaussdb(%s)." % (cmVersion, gaussdbVersion)) + + def createManualStartFile(self): + self.logger.log("Creating cluster_manual_start file.") + cmd = """ + if [ ! -f {gaussHome}/bin/cluster_manual_start ]; then + touch {gaussHome}/bin/cluster_manual_start + fi + """.format(gaussHome=self.gaussHome) + for host in self.hostNames: + status, output = self.executeCmdOnHost(host, cmd) + if status != 0: + self.logger.debug("Command: " + cmd) + errorDetail = "\nStatus: %s\nOutput: %s" % (status, output) + self.logger.logExit("Failed to create cluster_manual_start file." + errorDetail) + + def initCMServer(self): + self.logger.log("Initializing cm_server.") + for (cmdir, host) in zip(self.cmDirs, self.hostNames): + cmd = """ + cp {gaussHome}/share/config/cm_server.conf.sample {cmdir}/cm_server/cm_server.conf + sed 's#log_dir = .*#log_dir = {gaussLog}/cm/cm_server#' {cmdir}/cm_server/cm_server.conf -i + """.format(gaussHome=self.gaussHome, gaussLog=self.gaussLog, cmdir=cmdir) + status, output = self.executeCmdOnHost(host, cmd) + if status != 0: + self.logger.debug("Command: " + cmd) + errorDetail = "\nStatus: %s\nOutput: %s" % (status, output) + self.logger.logExit("Failed to initialize cm_server." + errorDetail) + + def initCMAgent(self): + self.logger.log("Initializing cm_agent.") + for (cmdir, host) in zip(self.cmDirs, self.hostNames): + cmd = """ + cp {gaussHome}/share/config/cm_agent.conf.sample {cmdir}/cm_agent/cm_agent.conf && + sed 's#log_dir = .*#log_dir = {gaussLog}/cm/cm_agent#' {cmdir}/cm_agent/cm_agent.conf -i && + sed 's#unix_socket_directory = .*#unix_socket_directory = {gaussHome}#' {cmdir}/cm_agent/cm_agent.conf -i + """.format(gaussHome=self.gaussHome, gaussLog=self.gaussLog, cmdir=cmdir) + status, output = self.executeCmdOnHost(host, cmd) + if status != 0: + self.logger.debug("Command: " + cmd) + errorDetail = "\nStatus: %s\nOutput: %s" % (status, output) + self.logger.logExit("Failed to initialize cm_agent." + errorDetail) + + def setMonitorCrontab(self): + """ + set om_monitor crontab + """ + self.logger.log("Setting om_monitor crontab.") + # save old crontab content to cronContentTmpFile + cronContentTmpFile = os.path.join(self.tmpPath, "cronContentTmpFile_" + str(os.getpid())) + listCronCmd = "crontab -l > %s" % cronContentTmpFile + status, output = self.executeCmdOnHost(self.localhostName, listCronCmd) + if status != 0: + self.logger.debug("Command: " + listCronCmd) + errorDetail = "\nStatus: %s\nOutput: %s" % (status, output) + self.logger.logExit(ErrorCode.GAUSS_508["GAUSS_50804"] + errorDetail) + # if old crontab content contains om_monitor, clear it + clearMonitorCmd = "sed '/.*om_monitor.*/d' %s -i" % cronContentTmpFile + status, output = subprocess.getstatusoutput(clearMonitorCmd) + if status != 0: + os.remove(cronContentTmpFile) + self.logger.debug("Command: " + clearMonitorCmd) + errorDetail = "\nStatus: %s\nOutput: %s" % (status, output) + self.logger.logExit("Failed to clear old om_monitor crontab." + errorDetail) + + # generate om_monitor crontab command and append it to cronContentTmpFile + startMonitorCmd = "source /etc/profile;(if [ -f ~/.profile ];" \ + "then source ~/.profile;fi);source ~/.bashrc;" + if self.envFile != "~/.bashrc": + startMonitorCmd += "source %s; " % (self.envFile) + monitorLogPath = os.path.join(self.gaussLog, "cm") + if not os.path.exists(monitorLogPath): + os.makedirs(monitorLogPath) + startMonitorCmd += "nohup om_monitor -L %s/om_monitor >>/dev/null 2>&1 &" % monitorLogPath + monitorCron = "*/1 * * * * " + startMonitorCmd + os.linesep + with open(cronContentTmpFile, 'a+', encoding='utf-8') as fp: + fp.writelines(monitorCron) + fp.flush() + + # set crontab on other hosts + setCronCmd = "crontab %s" % cronContentTmpFile + cleanTmpFileCmd = "rm %s -f" % cronContentTmpFile + for host in self.hostNames: + if host == self.localhostName: + continue + # copy cronContentTmpFile to other host + scpCmd = "scp %s %s:%s" % (cronContentTmpFile, host, self.tmpPath) + status, output = subprocess.getstatusoutput(scpCmd) + if status != 0: + self.logger.debug("Command: " + scpCmd) + errorDetail = "\nStatus: %s\nOutput: %s" % (status, output) + self.logger.logExit(("Failed to copy cronContentTmpFile to %s." % host) + errorDetail) + # set om_monitor crontab + status, output = self.executeCmdOnHost(host, setCronCmd) + # cleanup cronContentTmpFile + self.executeCmdOnHost(host, cleanTmpFileCmd) + if status != 0: + self.logger.debug("Command: " + setCronCmd) + errorDetail = "\nStatus: %s\nOutput: %s" % (status, output) + self.logger.logExit(ErrorCode.GAUSS_508["GAUSS_50801"] + errorDetail) + + # start om_monitor + status, output = self.executeCmdOnHost(host, startMonitorCmd) + if status != 0: + self.logger.debug("Command: " + startMonitorCmd) + errorDetail = "\nStatus: %s\nOutput: %s" % (status, output) + self.logger.logExit((ErrorCode.GAUSS_516["GAUSS_51607"] % "om_monitor") + errorDetail) + + # set crontab on localhost + status, output = subprocess.getstatusoutput(setCronCmd) + if status != 0: + self.logger.debug("Command: " + setCronCmd) + errorDetail = "\nStatus: %s\nOutput: %s" % (status, output) + self.logger.logExit(ErrorCode.GAUSS_508["GAUSS_50801"] + errorDetail) + os.remove(cronContentTmpFile) + + status, output = subprocess.getstatusoutput(startMonitorCmd) + if status != 0: + self.logger.debug("Command: " + startMonitorCmd) + errorDetail = "\nStatus: %s\nOutput: %s" % (status, output) + self.logger.logExit((ErrorCode.GAUSS_516["GAUSS_51607"] % "om_monitor") + errorDetail) + + def startCluster(self): + self.logger.log("Starting cluster.") + startCmd = "source %s; cm_ctl start" % self.envFile + status, output = subprocess.getstatusoutput(startCmd) + if status != 0: + self.logger.debug("Command: " + startCmd) + errorDetail = "\nStatus: %s\nOutput: %s" % (status, output) + self.logger.logExit("Failed to start cluster." + errorDetail) + queryCmd = "source %s; cm_ctl query -Cv" % self.envFile + status, output = subprocess.getstatusoutput(queryCmd) + if status != 0: + self.logger.debug("Command: " + queryCmd) + errorDetail = "\nStatus: %s\nOutput: %s" % (status, output) + self.logger.logExit("Failed to query cluster status." + errorDetail) + self.logger.log(output) + self.logger.log("Install CM tool success.") + + @staticmethod + def refreshStaticFile(envFile, xmlFile): + """ + refresh static and dynamic file using xml file with cm + """ + # refresh static file + cmd = """ + source {envFile}; + gs_om -t generateconf -X {xmlFile} --distribute + """.format(envFile=envFile, xmlFile=xmlFile) + status, output = subprocess.getstatusoutput(cmd) + errorDetail = "" + if status != 0: + errorDetail = "\nCommand: %s\nStatus: %s\nOutput: %s" % (cmd, status, output) + return status, errorDetail + + @staticmethod + def refreshDynamicFile(envFile): + # refresh dynamic file + getStatusCmd = "source %s; gs_om -t status --detail | grep 'Primary Normal' > /dev/null" % envFile + status, output = subprocess.getstatusoutput(getStatusCmd) + if status != 0: + CMLog.printMessage("Normal primary doesn't exist in the cluster, no need to refresh dynamic file.") + return 0, "" + refreshDynamicFileCmd = "source %s; gs_om -t refreshconf" % envFile + status, output = subprocess.getstatusoutput(refreshDynamicFileCmd) + errorDetail = "" + if status != 0: + errorDetail = "\nCommand: %s\nStatus: %s\nOutput: %s" % (refreshDynamicFileCmd, status, output) + return status, errorDetail + + def refreshStaticAndDynamicFile(self): + self.logger.log("Refreshing static and dynamic file using xml file with cm.") + status, output = InstallImpl.refreshStaticFile(self.envFile, self.xmlFile) + if status != 0: + self.logger.logExit("Failed to refresh static file." + output) + status, output = InstallImpl.refreshDynamicFile(self.envFile) + if status != 0: + self.logger.logExit("Failed to refresh dynamic file." + output) + + def run(self): + self.logger.log("Start to install cm tool.") + self.prepareCMPath() + self.decompressCMPkg() + self.createManualStartFile() + self.initCMServer() + self.initCMAgent() + self.refreshStaticAndDynamicFile() + self.setMonitorCrontab() + self.startCluster() diff --git a/tool/cm_tool/__init__.py b/tool/cm_tool/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tool/cm_tool/cm_install b/tool/cm_tool/cm_install new file mode 100644 index 0000000..af540a7 --- /dev/null +++ b/tool/cm_tool/cm_install @@ -0,0 +1,247 @@ +#!/usr/bin/env python3 +# -*- coding:utf-8 -*- +############################################################################# +# Copyright (c) 2022 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 : cm_install is a utility to deploy CM tool to openGauss database cluster. +############################################################################# + +import getopt +import os +import sys +import re +import subprocess +import xml.etree.cElementTree as ETree +from CMLog import CMLog +from Common import * +from ErrorCode import ErrorCode +from InstallImpl import InstallImpl + +sys.path.append(sys.path[0] + "/../../") + +class Install: + """ + The class is used to do perform installation + """ + + def __init__(self): + self.envFile = "" + self.xmlFile = "" + self.gaussHome = "" + self.gaussLog = "" + self.toolPath = "" + self.tmpPath = "" + self.cmDirs = [] + self.hostNames = [] + self.localhostName = "" + self.cmpkg = "" + + def getLocalhostName(self): + import socket + self.localhostName = socket.gethostname() + + def getEnvParams(self): + self.gaussHome = getEnvParam(self.envFile, "GAUSSHOME") + self.gaussLog = getEnvParam(self.envFile, "GAUSSLOG") + self.toolPath = getEnvParam(self.envFile, "GPHOME") + self.tmpPath = getEnvParam(self.envFile, "PGHOST") + + def checkXMLFile(self): + """ + function: check XML file + 1.check -X parameter + 2.check XML file exists + 3.check XML file an absolute path + 4.permission + input : NA + output: NA + """ + if self.xmlFile.startswith('~/'): + homePath = os.path.expanduser('~') + self.xmlFile = homePath + self.xmlFile[1:] + if not os.path.isfile(self.xmlFile): + CMLog.exitWithError(ErrorCode.GAUSS_502["GAUSS_50210"] % "xmlFile") + if not os.path.exists(self.xmlFile): + CMLog.exitWithError(ErrorCode.GAUSS_502["GAUSS_50201"] % "xmlFile") + if not os.path.isabs(self.xmlFile): + CMLog.exitWithError(ErrorCode.GAUSS_502["GAUSS_50213"] % "xmlFile") + if not os.access(self.xmlFile, os.R_OK): + CMLog.exitWithError(ErrorCode.GAUSS_501["GAUSS_50100"] % (self.xmlFile, "current user")) + + def checkExeUser(self): + if os.getuid() == 0: + CMLog.exitWithError(ErrorCode.GAUSS_501["GAUSS_50105"]) + + def usage(self): + """ +cm_install is a utility to deploy CM tool to openGauss database cluster. + +Usage: + cm_install -? | --help + cm_install -X XMLFILE [-e envFile] --cmpkg=cmpkgPath +General options: + -X Path of the XML configuration file. + -e Path of env file. + Default value "~/.bashrc". + --cmpkg Path of CM pacakage. + -?, --help Show help information for this + utility, and exit the command line mode. + """ + print(self.usage.__doc__) + + def parseCommandLine(self): + if len(sys.argv) == 1: + self.usage() + sys.exit(1) + + try: + opts, args = getopt.getopt(sys.argv[1:], "?X:e:", ["help", "cmpkg="]) + except getopt.GetoptError as e: + CMLog.exitWithError(ErrorCode.GAUSS_500["GAUSS_50000"] % str(e)) + + for opt, value in opts: + if opt in ("-?", "--help"): + self.usage() + sys.exit(0) + elif opt in ("-X"): + self.xmlFile = value + elif opt in ("-e"): + self.envFile = value + elif opt in ("--cmpkg"): + self.cmpkg = value + + def checkParam(self): + if self.xmlFile == "": + CMLog.exitWithError(ErrorCode.GAUSS_500["GAUSS_50001"] % 'X or xml' + ".") + + if self.cmpkg == "": + CMLog.exitWithError(ErrorCode.GAUSS_500["GAUSS_50001"] % 'p or cmpkg' + ".") + + if self.envFile == "": + self.envFile = "~/.bashrc" + + def checkOm(self): + """ + check whether there is om tool + """ + cmd = "source %s; gs_om --version" % self.envFile + status, output = subprocess.getstatusoutput(cmd) + if status != 0: + errorDetail = "\nCommand: %s\nStatus: %s\nOutput: %s\n" % ( + cmd, status, output) + CMLog.exitWithError("OM tool is required." + errorDetail) + + def checkXMLFileSecurity(self): + """ + function : check XML contain DTDs + input : String + output : NA + """ + # Check xml for security requirements + # if it have " /dev/null" % self.envFile + status, output = subprocess.getstatusoutput(checkCMExistCmd) + if status == 0: + CMLog.exitWithError("CM exists in current cluster.") + def run(self): + self.checkExeUser() + self.parseCommandLine() + self.checkParam() + self.checkOm() + self.checkCM() + self.checkXMLFile() + self.getEnvParams() + self.initLogger() + self.getLocalhostName() + self.getInfoListOfAllNodes() + self.checkHostTrust() + installImpl = InstallImpl(self) + installImpl.run() + +if __name__ == "__main__": + install = Install() + install.run() diff --git a/tool/cm_tool/cm_uninstall b/tool/cm_tool/cm_uninstall new file mode 100644 index 0000000..b175d89 --- /dev/null +++ b/tool/cm_tool/cm_uninstall @@ -0,0 +1,249 @@ +#!/usr/bin/env python3 +# -*- coding:utf-8 -*- +############################################################################# +# Copyright (c) 2022 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 : cm_install is a utility to uninstall CM tool to openGauss database cluster. +############################################################################# + +import os +import sys +import getopt +import subprocess +from CMLog import CMLog +from ErrorCode import ErrorCode +from InstallImpl import InstallImpl +from Common import executeCmdOnHost, getEnvParam, getLocalhostName + +class UnIntall: + def __init__(self) -> None: + self.envFile = "" + self.xmlFile = "" + self.bDeleteData = False + self.bDeleteBinary = False + self.hostnames = [] + self.cmDataPaths = [] + self.localhostName = getLocalhostName() + + def usage(self): + """ +cm_uninstall is a utility to deploy CM tool to openGauss database cluster. + +Usage: + cm_uninstall -? | --help + cm_uninstall -X XMLFILE [-e envFile] [--deleteData] [--deleteBinary] +General options: + -X Path of the XML configuration file. + -e Path of env file. + Default value "~/.bashrc". + --deleteData Specify to true if you want to remove cmdatapath and GAUSSLOG/cm. + --deleteBinary Specify to true if you want to remove CM binary file. + -?, --help Show help information for this + utility, and exit the command line mode. + """ + print(self.usage.__doc__) + + def parseCommandLine(self): + if len(sys.argv) == 1: + self.usage() + sys.exit(1) + + try: + opts, args = getopt.getopt(sys.argv[1:], "?X:e:", + ["help", "deleteData", "deleteBinary"]) + except getopt.GetoptError as e: + CMLog.exitWithError(ErrorCode.GAUSS_500["GAUSS_50000"] % str(e)) + + for opt, value in opts: + if opt in ("-?", "--help"): + self.usage() + sys.exit(0) + elif opt in ("-X"): + self.xmlFile = value + elif opt in ("-e"): + self.envFile = value + elif opt in ("--deleteData"): + self.bDeleteData = True + elif opt in ("--deleteBinary"): + self.bDeleteBinary = True + + def checkParam(self): + if self.xmlFile == "": + CMLog.exitWithError( + ErrorCode.GAUSS_500["GAUSS_50001"] % 'X' + ".") + + if self.envFile == "": + self.envFile = "~/.bashrc" + + def getHostnames(self): + """ + Get hostnames of all nodes from static file. + """ + self.logger.debug("Getting hostnames") + cmd = "source %s; cm_ctl view | grep 'nodeName'" % self.envFile + status, output = subprocess.getstatusoutput(cmd) + if status != 0: + self.logger.logExit((ErrorCode.GAUSS_512["GAUSS_51203"] % "hostnames") + output) + hostnames = output.split('\n') + for i in range(0, len(hostnames)): + hostname = hostnames[i].split(':')[1].strip() + self.hostnames.append(hostname) + self.logger.debug("hostnames=" + ','.join(self.hostnames)) + + def getCMDataPaths(self): + """ + Get cmDataPaths of all nodes from static file. + """ + if not self.bDeleteData: + return + self.logger.debug("Getting CM datapaths.") + cmd = "source %s; cm_ctl view | grep -E 'cmDataPath'" % self.envFile + status, output = subprocess.getstatusoutput(cmd) + if status != 0: + self.logger.logExit((ErrorCode.GAUSS_512["GAUSS_51203"] % "cmDataPaths") + output) + cmDataPaths = output.split('\n') + for p in cmDataPaths: + cmDataPath = p.split(':')[1].strip() + self.cmDataPaths.append(cmDataPath) + if self.cmDataPaths == []: + self.logger.logExit("") + self.logger.debug("cmDataPaths=" + ','.join(self.cmDataPaths)) + + def cancleMonitorCrontab(self): + """ + Cancle monitor crontab of all nodes. + """ + self.logger.log("Cancling monitor crontab.") + cronContentTmpFile = os.path.join("/tmp", "cronContentTmpFile_" + str(os.getpid())) + cmd = """ + crontab -l > {cronContentTmpFile}; + sed '/.*om_monitor.*/d' {cronContentTmpFile} -i; + crontab {cronContentTmpFile} + """.format(cronContentTmpFile=cronContentTmpFile) + for host in self.hostnames: + status, output = executeCmdOnHost(host, cmd) + if status != 0: + errorDetail = "\nCommand: %s\nStatus: %s\nOutput: %s" % (cmd, status, output) + self.logger.logExit(("Failed to cancle monitor crontab on host %s." % host) + errorDetail) + + def stopCMProcess(self): + """ + Stop CM process of all nodes, includeing om_monitor, cm_agent, cm_server, gaussdb fence + """ + self.logger.log("Stopping CM process.") + # When you execute the awk command through Python, sometimes the awk command is invalid, + # just like your command does not use the awk command. Therefore, we have to avoid using awk. + getPidsCmd = "ps -xo pid,command | grep -E 'om_monitor|cm_agent|cm_server|fenced UDF' | grep -v grep" + for host in self.hostnames: + isLocal = False + if host == self.localhostName: + isLocal = True + # get CM process pids + status, output = executeCmdOnHost(host, getPidsCmd, isLocal) + self.logger.debug("Command: " + getPidsCmd) + self.logger.debug("Status: " + str(status)) + self.logger.debug("Output: " + output) + if output == "": + continue + processList = output.strip().split('\n') + pidList = [] + for process in processList: + pid = process.split()[0] + if pid.isdigit(): + pidList.append(pid) + if pidList == []: + continue + # kill CM process + pidsStr = ' '.join(pidList) + killCMProcessCmd = "kill -9 " + pidsStr + status, output = executeCmdOnHost(host, killCMProcessCmd, isLocal) + if status != 0: + errorDetail = "\nCommand: %s\nStatus: %s\nOutput: %s" % (killCMProcessCmd, status, output) + self.logger.logExit((ErrorCode.GAUSS_516["GAUSS_51606"] % "CM") + errorDetail) + + def refreshStaticAndDynamicFile(self): + self.logger.log("Refreshing static and dynamic file using xml file without cm.") + status, output = InstallImpl.refreshStaticFile(self.envFile, self.xmlFile) + if status != 0: + self.logger.logExit("Failed to refresh static file." + output) + status, output = InstallImpl.refreshDynamicFile(self.envFile) + if status != 0: + self.logger.logExit("Failed to refresh dynamic file." + output) + + def deleteData(self): + """ + remove cmdatapath + """ + if not self.bDeleteData: + return + self.logger.log("Deleting CM data path.") + for host, path in zip(self.hostnames, self.cmDataPaths): + isLocal = False + if host == self.localhostName: + isLocal = True + cmd = "source %s; rm -rf %s" % (self.envFile, path) + status, output = executeCmdOnHost(host, cmd, isLocal) + if status != 0: + errorDetail = "\nCommand: %s\nStatus: %s\nOutput: %s" % (cmd, status, output) + self.logger.exitWithError(("Failed to delete CM data path on host %s." % host) + errorDetail) + + def deleteBinary(self): + """ + delete CM binaries, include om_monitor, cm_agent, cm_server, cm_ctl + """ + if not self.bDeleteBinary: + return + self.logger.log("Deleting CM binaries.") + for host in self.hostnames: + isLocal = False + if host == self.localhostName: + isLocal = True + cmd = "source %s; cd $GAUSSHOME/bin; rm -f om_monitor cm_agent cm_server cm_ctl; cd -" % self.envFile + status, output = executeCmdOnHost(host, cmd, isLocal) + if status != 0: + errorDetail = "\nCommand: %s\nStatus: %s\nOutput: %s" % (cmd, status, output) + self.logger.exitWithError(("Failed to delete CM binaries on host %s." % host) + errorDetail) + + def initLogger(self): + gaussLog = getEnvParam(self.envFile, "GAUSSLOG") + logPath = os.path.join(gaussLog, "cm", "cm_tool") + if not os.path.exists(logPath): + os.makedirs(logPath) + self.logger = CMLog(logPath, module="cm_uninstall", prefix="cm_uninstall") + + def checkExeUser(self): + if os.getuid() == 0: + CMLog.exitWithError(ErrorCode.GAUSS_501["GAUSS_50105"]) + + def run(self): + self.checkExeUser() + self.parseCommandLine() + self.checkParam() + self.initLogger() + self.logger.log("Start to uninstall CM.") + self.getHostnames() + self.getCMDataPaths() + self.cancleMonitorCrontab() + self.stopCMProcess() + self.refreshStaticAndDynamicFile() + self.deleteData() + self.deleteBinary() + self.logger.log("Uninstall CM tool success.") + + +if __name__ == "__main__": + unInstall = UnIntall() + unInstall.run() \ No newline at end of file