Files
openGauss-OM/script/local/CheckConfig.py
coolany eae422baf3 适配CM组件
Signed-off-by: coolany <kyosang@163.com>

support cgroup

追加合入
2022-03-05 18:51:52 +08:00

474 lines
17 KiB
Python

#!/usr/bin/env python3
# -*- 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 : CheckConfig.py is a local utility to
# execute some functions about init instance
#############################################################################
import subprocess
import getopt
import sys
import os
sys.path.append(sys.path[0] + "/../")
from gspylib.common.GaussLog import GaussLog
from gspylib.common.ParameterParsecheck import Parameter
from gspylib.common.Common import DefaultValue
from gspylib.common.LocalBaseOM import LocalBaseOM
from gspylib.common.ErrorCode import ErrorCode
from domain_utils.cluster_file.cluster_dir import ClusterDir
from domain_utils.cluster_file.cluster_log import ClusterLog
from base_utils.os.env_util import EnvUtil
from base_utils.os.file_util import FileUtil
from domain_utils.cluster_file.version_info import VersionInfo
from base_utils.os.net_util import NetUtil
from domain_utils.domain_common.cluster_constants import ClusterConstants
from base_utils.common.constantsbase import ConstantsBase
from domain_utils.cluster_os.cluster_user import ClusterUser
#############################################################################
# Global variables
# TIME_OUT: set time out
# self.logger: globle logger
# g_clusterUser: global user information
#############################################################################
TIME_OUT = 2
class CheckNodeEnv(LocalBaseOM):
"""
function: Init all instance on local node
input : NA
output: NA
"""
def __init__(self, logFile, clusterUser, dataParams, instIds):
"""
function: init function
input : logFile, clusterUser, dataParams, instIds
output: NA
"""
LocalBaseOM.__init__(self, logFile, clusterUser)
self.__dataGucParams = dataParams[:]
self.__instanceIds = instIds[:] # if is empty, check all instances
self.clusterInfo = None
self.dbNodeInfo = None
self.__diskSizeInfo = {}
self.__pgsqlFiles = []
def run(self):
"""
function: Init instance on local node:
1.Check GaussDB Log directory
2.Check pgsql directory
3.Check instances config on local node
4.Set manual start
5.Set linux cron
input : NA
output: NA
"""
self.__checkParameters()
self.readConfigInfo()
self.logger.debug("Instance information on local node:\n%s."
% str(self.dbNodeInfo))
self.initComponent()
# Check GaussDB Log directory
self.__checkGaussLogDir()
# Check pgsql directory
self.__checkPgsqlDir()
# Check instances config on local node
self.__checkNodeConfig()
# Set manual start
self.__set_manual_start()
# Set linux cron
self.__set_cron()
self.logger.log("Checked the configuration file on node[%s]"
" successfully." % NetUtil.GetHostIpOrName())
def __checkParameters(self):
"""
function: Check parameters for instance config:
1.Check parameter for configuring CNs
2.Check parameter for configuring DNs
input : NA
output: NA
"""
self.logger.log("Checking parameters for configuring DNs.")
for param in self.__dataGucParams:
if self.__checkconfigParams(param.strip()) != 0:
self.logger.logExit(ErrorCode.GAUSS_500["GAUSS_50000"]
% param)
def __checkconfigParams(self, param):
"""
function: Check parameter for postgresql.conf,
port : this is calculated automatically
input : param
output: 0/1
"""
configInvalidArgs = ["port"]
argList = param.split("=")
for arg in configInvalidArgs:
if (arg in argList):
return 1
return 0
def __checkGaussLogDir(self):
"""
function: Check GaussDB Log directory:
1.check user base log directory
2.create instance log directory
3.change directory mode
input : NA
output: NA
"""
# check user base log dir
user_dir = ClusterDir.getUserLogDirWithUser(self.user)
self.logger.log("Checking %s log directory[%s]."
% (VersionInfo.PRODUCT_NAME, user_dir))
if (not os.path.exists(user_dir)):
self.logger.logExit(ErrorCode.GAUSS_502["GAUSS_50201"]
% ('user base log directory [%s]' % user_dir))
##make gs_profile dir
user_profile_dir = os.path.join(user_dir, "gs_profile")
self.__makeDirForDBUser(user_profile_dir, "user_profile_dir")
##make pg_log dir and pg_audit dir
user_pg_log_dir = os.path.join(user_dir, "pg_log")
self.__makeDirForDBUser(user_pg_log_dir, "user_pg_log_dir")
user_pg_audit_dir = os.path.join(user_dir, "pg_audit")
self.__makeDirForDBUser(user_pg_audit_dir, "user_pg_audit_dir")
##make bin log dir
user_bin_dir = os.path.join(user_dir, "bin")
self.__makeDirForDBUser(user_bin_dir, "user_bin_dir")
for inst in self.dbNodeInfo.datanodes:
log_dir_name = "dn_%d" % (inst.instanceId)
log_dir = os.path.join(user_pg_log_dir, log_dir_name)
audit_dir = os.path.join(user_pg_audit_dir, log_dir_name)
self.__makeDirForDBUser(log_dir, "user_pg_log_%s_dir"
% log_dir_name)
self.__makeDirForDBUser(audit_dir, "user_pg_audit_%s_dir"
% log_dir_name)
try:
self.logger.debug("Command to find directory in directory[%s] "
% user_dir)
# change directory mode
FileUtil.getchangeDirModeCmd(user_dir)
self.logger.debug("Command to find file in directory[%s] "
% user_dir)
# change log file mode
FileUtil.getchangeFileModeCmd(user_dir)
self.logger.debug("Command to change the obs log setting.")
# change the obs log setting file distribute package
self.changeObsLogSetting()
except Exception as e:
self.logger.logExit(str(e))
def changeObsLogSetting(self):
"""
function: change the obs log setting file distribute package
input : NA
output: NA
"""
obspathNum = self.clusterInfo.appPath.count("/")
"""
obs path is the relative path between log path and app path.
if app path is /test/app and log path is /test/log
then the relative path from app to log is '..'+'/..'*(num-1)+logpath
the relative path from obs to log is '../../..'+'/..'*(num-1)+logpath
"""
username = EnvUtil.getEnv("LOGNAME")
DefaultValue.checkPathVaild(username)
obspath = "LogPath=../.." + "/.." * obspathNum + "%s/" \
% self.clusterInfo.logPath + "%s" % username + "/bin/gs_obs"
cmd = "mkdir -p '%s/%s/bin/gs_obs' -m %s" \
% (self.clusterInfo.logPath, username,
DefaultValue.KEY_DIRECTORY_MODE)
(status, output) = subprocess.getstatusoutput(cmd)
if (status != 0):
self.logger.debug("The cmd is %s " % cmd)
raise Exception(ErrorCode.GAUSS_502["GAUSS_50208"] % "obs log"
+ " Error: \n%s " % output)
obsinifile = "%s/lib/OBS.ini" % self.clusterInfo.appPath
if not os.path.exists(obsinifile):
self.logger.logExit(ErrorCode.GAUSS_502["GAUSS_50201"]
% obsinifile)
try:
with open(obsinifile, 'r') as fp:
lines = fp.readlines()
flen = len(lines) - 1
for i in range(flen):
if "sdkname=eSDK-OBS-API-Linux-C" in lines[i]:
lines[i] = lines[i].replace("sdkname=eSDK-OBS-API-Linux-C",
"sdkname=gs_obs")
if "LogPath=../logs" in lines[i]:
lines[i] = lines[i].replace("LogPath=../logs", obspath)
with open(obsinifile, 'w') as fpw:
fpw.writelines(lines)
except Exception as e:
self.logger.logExit(str(e))
def __makeDirForDBUser(self, path, desc):
"""
function: Create a dir for DBUser:
1.create a dir for DB user
2.Check if target directory is writeable for user
input : path, desc
output: NA
"""
self.logger.debug("Making %s directory[%s] for database node user."
% (desc, path))
FileUtil.createDirectory(path)
FileUtil.changeMode(DefaultValue.KEY_DIRECTORY_MODE, path)
if not FileUtil.checkDirWriteable(path):
self.logger.logExit(ErrorCode.GAUSS_501["GAUSS_50102"]
% (path, self.user))
def __checkPgsqlDir(self):
"""
function: 1.Check pgsql directory
2.change permission
3.Check if target directory is writeable for user
input : NA
output: NA
"""
tmpDir = EnvUtil.getTmpDirFromEnv()
self.logger.log("Checking directory [%s]." % tmpDir)
if (not os.path.exists(tmpDir)):
self.logger.logExit(ErrorCode.GAUSS_502["GAUSS_50201"]
% tmpDir + " Please create it first.")
self.__pgsqlFiles = os.listdir(tmpDir)
FileUtil.changeMode(DefaultValue.KEY_DIRECTORY_MODE, tmpDir)
if not FileUtil.checkDirWriteable(tmpDir):
self.logger.logExit(ErrorCode.GAUSS_501["GAUSS_50102"]
% (tmpDir, self.user))
def check_cm_agent_config(self):
"""
function: Check cm_agent configuration
input : NA
output: NA
"""
for cmaInst in self.dbNodeInfo.cmagents:
if len(self.__instanceIds) != 0 and cmaInst.instanceId not in self.__instanceIds:
continue
self.__checkDataDir(cmaInst.datadir)
def check_cm_server_config(self):
"""
function: Check cm_server configuration
input : NA
output: NA
"""
for cmsInst in self.dbNodeInfo.cmservers:
if len(self.__instanceIds) != 0 and cmsInst.instanceId not in self.__instanceIds:
continue
self.__checkDataDir(cmsInst.datadir)
def checkDNConfig(self):
"""
function: Check DN configuration
input : NA
output: NA
"""
for dnInst in self.dbNodeInfo.datanodes:
if (len(self.__instanceIds) != 0 and
dnInst.instanceId not in self.__instanceIds):
continue
self.__checkDataDir(dnInst.datadir)
if (len(dnInst.ssdDir) != 0):
self.__checkDataDir(dnInst.ssdDir)
def __checkNodeConfig(self):
"""
function: Check instances config on local node
input : NA
output: NA
"""
self.logger.log("Checking CM data directory.")
if self.dbNodeInfo.cmDataDir:
self.__checkDataDir(self.dbNodeInfo.cmDataDir, False)
self.logger.log("Checking CMAgent configuration file.")
self.check_cm_agent_config()
self.logger.log("Checking CMServer configuration file.")
self.check_cm_server_config()
self.logger.log("Checking database node configuration.")
self.checkDNConfig()
def __checkDataDir(self, datadir, checkEmpty=True, checkSize=True):
"""
function: Check if directory exists and disk size lefted
input : datadir, checkEmpty, checkSize
output: NA
"""
self.logger.log("Checking directory [%s]." % datadir)
# Check and create directory
ownerPath = datadir
if (os.path.exists(datadir)):
if (checkEmpty):
fileList = os.listdir(datadir)
# full_upgrade_bak is backup path for datapath and install path
# we should skip it
if ("full_upgrade_bak" in fileList):
fileList.remove("full_upgrade_bak")
if ("pg_location" in fileList):
fileList.remove("pg_location")
if (len(fileList) != 0):
self.logger.logExit(ErrorCode.GAUSS_502["GAUSS_50202"]
% datadir)
else:
while True:
(ownerPath, dirName) = os.path.split(ownerPath)
if (os.path.exists(ownerPath) or dirName == ""):
ownerPath = os.path.join(ownerPath, dirName)
os.makedirs(datadir,
ConstantsBase.KEY_DIRECTORY_PERMISSION)
break
# Check if data directory is writeable
if not FileUtil.checkDirWriteable(datadir):
self.logger.logExit(ErrorCode.GAUSS_501["GAUSS_50102"]
% (datadir, self.user))
if (checkSize):
self.__diskSizeInfo = DefaultValue.checkDirSize(
datadir, DefaultValue.INSTANCE_DISK_SIZE, self.logger)
def __set_manual_start(self):
"""
function: Set manual start
input : NA
output: NA
"""
self.logger.log("Setting manual start.")
if len(self.__instanceIds) == 0:
manual_start_file = "%s/bin/cluster_manual_start" % self.clusterInfo.appPath
FileUtil.createFile(manual_start_file)
FileUtil.changeMode(DefaultValue.KEY_FILE_MODE, manual_start_file)
host_name = NetUtil.GetHostIpOrName()
db_node = self.clusterInfo.getDbNodeByName(host_name)
if not db_node:
self.logger.logExit(ErrorCode.GAUSS_512["GAUSS_51209"] % ("NODE", host_name))
else:
for instId in self.__instanceIds:
if (instId in self.dbNodeInfo.coordinators) or \
(instId in self.dbNodeInfo.datanodes) or \
(instId in self.dbNodeInfo.gtms):
inst_start_file = "%s/bin/instance_manual_start_%d" % (
self.clusterInfo.appPath, instId)
FileUtil.createFile(inst_start_file)
FileUtil.changeMode(DefaultValue.KEY_FILE_MODE, inst_start_file)
def __set_cron(self):
"""
function: Set linux cron
input : NA
output: NA
"""
if self.cmCons and self.cmCons[0].instInfo.datadir == "/cm_agent" and \
not os.path.exists(self.cmCons[0].instInfo.datadir):
self.logger.debug("No CM instance configuration.No need to set crontab.")
return
self.cmCons[0].setMonitor(self.user)
def usage():
"""
Usage:
python3 CheckConfig.py -h | --help
python3 CheckConfig.py -U user
[-i instId [...]]
[-C "PARAMETER=VALUE" [...]]
[-D "PARAMETER=VALUE" [...]]
[-l logfile]
"""
print(usage.__doc__)
def main():
"""
function: main function
input : NA
output: NA
"""
try:
opts, args = getopt.getopt(sys.argv[1:], "U:C:D:i:l:h", ["help"])
except Exception as e:
usage()
GaussLog.exitWithError(ErrorCode.GAUSS_500["GAUSS_50000"]
% str(e))
if (len(args) > 0):
GaussLog.exitWithError(ErrorCode.GAUSS_500["GAUSS_50000"]
% str(args[0]))
logFile = ""
dataParams = []
instanceIds = []
for (key, value) in opts:
if (key == "-h" or key == "--help"):
usage()
sys.exit(0)
elif (key == "-U"):
clusterUser = value
elif (key == "-D"):
dataParams.append(value)
elif (key == "-l"):
logFile = os.path.realpath(value)
elif (key == "-i"):
if (value.isdigit()):
instanceIds.append(int(value))
else:
GaussLog.exitWithError(ErrorCode.GAUSS_500["GAUSS_50004"]
% "i")
Parameter.checkParaVaild(key, value)
# check if user exist and is the right user
ClusterUser.checkUser(clusterUser)
# check log dir
if (logFile == ""):
logFile = ClusterLog.getOMLogPath(ClusterConstants.LOCAL_LOG_FILE,
clusterUser, "", "")
try:
checker = CheckNodeEnv(logFile, clusterUser,
dataParams, instanceIds)
checker.run()
sys.exit(0)
except Exception as e:
GaussLog.exitWithError(str(e))
if __name__ == '__main__':
main()