# -*- 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. # ---------------------------------------------------------------------------- import os import json import configparser from gspylib.common.DbClusterInfo import dbClusterInfo from gspylib.inspection.common import SharedFuncs from gspylib.common.ErrorCode import ErrorCode from gspylib.inspection.common.CheckItem import BaseItem from gspylib.inspection.common.CheckResult import ResultStatus from base_utils.os.net_util import NetUtil # master MASTER_INSTANCE = 0 # standby STANDBY_INSTANCE = 1 # dummy standby DUMMY_STANDBY_INSTANCE = 2 # cn INSTANCE_ROLE_COODINATOR = 3 # dn INSTANCE_ROLE_DATANODE = 4 g_gucDist = {} g_ignoreList = [] g_logicList = [] class CheckGUCConsistent(BaseItem): def __init__(self): super(CheckGUCConsistent, self).__init__(self.__class__.__name__) def preCheck(self): # check the threshold was set correctly if (not self.threshold.__contains__('version')): raise Exception(ErrorCode.GAUSS_530["GAUSS_53013"] % "version") self.version = self.threshold['version'] def checkLogicCluster(self): clusterInfo = dbClusterInfo() staticConfigDir = os.path.join(self.cluster.appPath, "bin") cmd = "find %s -name *.cluster_static_config" % staticConfigDir output = SharedFuncs.runShellCmd(cmd) if output: for staticConfigFile in output.splitlines(): clusterInfo.initFromStaticConfig(self.user, staticConfigFile, True) lcName = os.path.splitext(os.path.basename(staticConfigFile))[ 0] for dbnode in clusterInfo.dbNodes: if (dbnode.name == NetUtil.GetHostIpOrName()): return [lcName, dbnode] return ["", None] else: return ["", None] def getIgnoreParameters(self, configFile, ignoreSection, logicSection): global g_ignoreList global g_logicList fp = configparser.RawConfigParser() fp.read(configFile) secs = fp.sections() if (ignoreSection not in secs): return g_ignoreList = fp.options(ignoreSection) if self.cluster.isSingleInstCluster(): g_ignoreList.append("synchronous_standby_names") g_logicList = fp.options(logicSection) def checkInstanceGucValue(self, Instance, needm, lcName="", logicCluster=False): """ get CN/DN instance guc parameters """ global g_gucDist LCInstanceGucDist = {} lcInstance = {} sqlcmd = "select name,setting from pg_settings where category != 'Customized Options';" InstanceGucDist = {} output = SharedFuncs.runSqlCmd(sqlcmd, self.user, "", Instance.port, self.tmpPath, "postgres", self.mpprcFile, needm) gucValueList = output.split('\n') for gucValue in gucValueList: if (len(gucValue.split('|')) == 2): (parameter, value) = gucValue.split('|') if ( parameter == "transaction_read_only" and Instance.instanceRole == INSTANCE_ROLE_DATANODE): continue if (parameter not in g_ignoreList): if (not logicCluster): InstanceGucDist[parameter] = value else: if (parameter not in g_logicList): InstanceGucDist[parameter] = value elif (lcName and parameter in g_logicList): LCInstanceGucDist[parameter] = value else: continue if (lcName): instanceName = "%s_%s_%s" % (lcName, "DN", Instance.instanceId) lcInstance[instanceName] = LCInstanceGucDist return lcInstance if Instance.instanceRole == INSTANCE_ROLE_DATANODE: Role = "DN" instanceName = "%s_%s" % (Role, Instance.instanceId) g_gucDist[instanceName] = InstanceGucDist def doCheck(self): """ """ global g_gucDist # get ignore list dirName = os.path.dirname(os.path.realpath(__file__)) configFile = "%s/../../config/check_list_%s.conf" % ( dirName, self.version) self.getIgnoreParameters(configFile, 'guc_ignore', 'guc_logic') DNidList = [] result = [] logicCluster = False nodeInfo = self.cluster.getDbNodeByName(self.host) masterDnList = SharedFuncs.getMasterDnNum(self.user, self.mpprcFile) for DnInstance in nodeInfo.datanodes: if (DnInstance.instanceType != DUMMY_STANDBY_INSTANCE): DNidList.append(DnInstance) if len(DNidList) < 1: raise Exception(ErrorCode.GAUSS_512["GAUSS_51249"]) # get information of logicCluster on current node (lcName, dbnode) = self.checkLogicCluster() if (dbnode): logicCluster = True for DnInstance in dbnode.datanodes: if (DnInstance.instanceType != DUMMY_STANDBY_INSTANCE): if (DnInstance.instanceId in masterDnList): needm = False else: needm = True result.append( self.checkInstanceGucValue(DnInstance, needm, lcName, logicCluster)) g_gucDist[lcName] = result # test database Connection for Instance in DNidList: if not Instance: continue sqlcmd = "select pg_sleep(1);" if Instance.instanceId in masterDnList: needm = False else: needm = True SharedFuncs.runSqlCmd(sqlcmd, self.user, "", Instance.port, self.tmpPath, 'postgres', self.mpprcFile, needm) self.checkInstanceGucValue(Instance, needm, "", logicCluster) self.result.val = json.dumps(g_gucDist) self.result.raw = str(g_gucDist) self.result.rst = ResultStatus.OK def postAnalysis(self, itemResult): errors = [] ngs = [] dnGucDist = {} lcdnGucDist = {} for i in itemResult.getLocalItems(): if (i.rst == ResultStatus.ERROR): errors.append("%s: %s" % (i.host, i.val)) if (i.rst == ResultStatus.NG): ngs.append("%s: %s" % (i.host, i.val)) if (len(errors) > 0): itemResult.rst = ResultStatus.ERROR itemResult.analysis = "\n".join(errors) return itemResult if (len(ngs) > 0): itemResult.rst = ResultStatus.NG itemResult.analysis = "\n".join(ngs) return itemResult for v in itemResult.getLocalItems(): gucDist = json.loads(v.val) for InstanceName in gucDist.keys(): if (InstanceName[:2] == 'DN'): dnGucDist[InstanceName] = gucDist[InstanceName] else: if InstanceName in lcdnGucDist.keys(): lcdnGucDist[InstanceName].extend(gucDist[InstanceName]) else: lcdnGucDist[InstanceName] = gucDist[InstanceName] for parameter in dnGucDist[list(dnGucDist.keys())[0]].keys(): InstanceName = list(dnGucDist.keys())[0] keyValue = dnGucDist[InstanceName][parameter] relultStr = "\n%s:\n%s: %s\n" % (parameter, InstanceName, keyValue) flag = True for dnInstance in list(dnGucDist.keys())[1:]: value = dnGucDist[dnInstance][parameter] relultStr += "%s: %s\n" % (dnInstance, value) if (value != keyValue): flag = False if (not flag): itemResult.analysis += relultStr for lcName in lcdnGucDist.keys(): lcInstanceResult = lcdnGucDist[lcName] baseDn = lcInstanceResult[0] baseParameter = baseDn[list(baseDn.keys())[0]] for parameter in baseParameter.keys(): keyValue = baseParameter[parameter] relultStr = "\n%s:\n%s: %s\n" % ( parameter, list(baseDn.keys())[0], keyValue) flag = True for otherDn in lcInstanceResult[1:]: dnInstance = list(otherDn.keys())[0] value = otherDn[dnInstance][parameter] relultStr += "%s: %s\n" % (dnInstance, value) if (value != keyValue): flag = False if (not flag): itemResult.analysis += relultStr if (itemResult.analysis): itemResult.rst = ResultStatus.NG else: itemResult.rst = ResultStatus.OK itemResult.analysis = "All DN instance guc value is consistent." return itemResult