474 lines
17 KiB
Python
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()
|