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

support cgroup

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

534 lines
18 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 : CheckUpgrade.py is a utility to check the env before upgrade.
#############################################################################
import getopt
import sys
import os
import subprocess
import pwd
import traceback
sys.path.append(sys.path[0] + "/../")
from gspylib.common.GaussLog import GaussLog
from gspylib.common.DbClusterInfo import dbClusterInfo
from gspylib.common.ParameterParsecheck import Parameter
from gspylib.common.ErrorCode import ErrorCode
import impl.upgrade.UpgradeConst as Const
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.package_info import PackageInfo
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
INSTANCE_TYPE_UNDEFINED = -1
MASTER_INSTANCE = 0
STANDBY_INSTANCE = 1
DUMMY_STANDBY_INSTANCE = 2
#############################################################################
# Global variables
#############################################################################
g_logger = None
g_clusterInfo = None
class CmdOptions():
"""
Class for defining some cmd options
"""
def __init__(self):
self.action = ""
# the current old appPath
self.appPath = ""
self.user = ""
self.logFile = ""
self.xmlFile = ""
self.upgrade_version = ""
self.newAppPath = ""
class CheckUpgrade():
"""
Class to Check application setting for upgrade
"""
def __init__(self, appPath, action, newAppPath):
'''
Constructor
'''
self.appPath = appPath
self.action = action
self.newAppPath = newAppPath
def run(self):
"""
function: Check upgrade environment
input: NA
output: NA
"""
self.__checkSHA256()
self.__checkAppPath()
self.__checkDataDir()
if self.action == Const.ACTION_INPLACE_UPGRADE:
self.__checkBackupDir()
self.__checkAppVersion()
self.__backupDbClusterInfo()
def __checkAppPath(self):
"""
function: check app path
input: NA
output: NA
"""
if not os.path.isdir(self.appPath):
g_logger.logExit(ErrorCode.GAUSS_502["GAUSS_50201"]
% self.appPath)
static_config = "%s/bin/cluster_static_config" % self.appPath
if not os.path.exists(static_config):
g_logger.logExit(ErrorCode.GAUSS_502["GAUSS_50201"]
% static_config)
if not os.path.isfile(static_config):
g_logger.logExit(ErrorCode.GAUSS_502["GAUSS_50210"]
% static_config)
if not os.path.isdir(self.newAppPath):
g_logger.logExit(ErrorCode.GAUSS_502["GAUSS_50201"]
% self.newAppPath)
if os.path.samefile(self.newAppPath, self.appPath):
g_logger.logExit(ErrorCode.GAUSS_502["GAUSS_50233"]
% ("install path", "$GAUSSHOME"))
# check if the current app path is correct size,
# there should be no personal data
cmd = "du -hms %s | awk '{print $1}'" % os.path.realpath(self.appPath)
(status, output) = subprocess.getstatusoutput(cmd)
if (status != 0):
g_logger.logExit(ErrorCode.GAUSS_514["GAUSS_51400"] % cmd
+ " ERROR: %s" % str(output))
appSize = output
cmd = "du -hms %s/lib/postgresql/pg_plugin | awk '{print $1}'" \
% os.path.realpath(self.appPath)
(status, output) = subprocess.getstatusoutput(cmd)
if (status != 0):
g_logger.logExit(ErrorCode.GAUSS_514["GAUSS_51400"] % cmd +
" ERROR: %s" % str(output))
pluginSize = output
if int(appSize) - int(pluginSize) > Const.MAX_APP_SIZE:
g_logger.logExit(ErrorCode.GAUSS_504["GAUSS_50401"]
% (self.appPath, "%dM" % Const.MAX_APP_SIZE) +
"\nThere may be personal data in path %s,"
" please move your data to other directory"
% self.appPath)
def __checkAppVersion(self):
"""
function: Check version
input: NA
output: NA
"""
# grey upgrade no need do this check
curVer = VersionInfo.getAppVersion(self.appPath)
if (curVer == ""):
g_logger.logExit(ErrorCode.GAUSS_516["GAUSS_51623"])
gaussHome = EnvUtil.getEnvironmentParameterValue("GAUSSHOME",
g_opts.user)
if not gaussHome:
g_logger.logExit(ErrorCode.GAUSS_518["GAUSS_51800"]
% "$GAUSSHOME")
gaussdbFile = "%s/bin/gaussdb" % gaussHome
cmd = "%s --version 2>/dev/null" % (gaussdbFile)
(status, output) = subprocess.getstatusoutput(cmd)
if (status != 0):
g_logger.logExit(ErrorCode.GAUSS_514["GAUSS_51400"] % cmd
+ "Error:\n %s" % output)
def __checkSHA256(self):
'''
function: Check the sha256 of new version
input: NA
output: NA
'''
try:
PackageInfo.checkPackageOS()
except Exception as e:
g_logger.logExit(str(e))
def __getTmpDir(self):
"""
"""
return EnvUtil.getTmpDirFromEnv()
def __getBackupDir(self):
"""
"""
return "%s/binary_upgrade" % EnvUtil.getTmpDirFromEnv()
def __backupDbClusterInfo(self):
"""
function: backup DbClusterInfo.py and cluster_static_config to temp
path
input: NA
output: NA
"""
commonStaticConfigFile = "%s/bin/cluster_static_config" \
% g_opts.appPath
commonUpgradeVersionFile = "%s/bin/upgrade_version" % g_opts.appPath
commonDbClusterInfoModule = \
"%s/bin/script/gspylib/common/DbClusterInfo.py" % g_opts.appPath
bakPath = self.__getTmpDir()
# backup DbClusterInfo.py
oldDbClusterInfoModule = "%s/OldDbClusterInfo.py" % bakPath
cmd = "cp -p '%s' '%s'" % (commonDbClusterInfoModule,
oldDbClusterInfoModule)
cmd += " && cp -rp '%s/bin/script/' '%s'" % (g_opts.appPath, bakPath)
(status, output) = subprocess.getstatusoutput(cmd)
if (status != 0):
g_logger.logExit(ErrorCode.GAUSS_514["GAUSS_51400"] % cmd
+ "\nOutput:%s" % output)
# backup cluster_static_config
cmd = "cp -p '%s' '%s'/" % (commonStaticConfigFile, bakPath)
(status, output) = subprocess.getstatusoutput(cmd)
if (status != 0):
g_logger.logExit(ErrorCode.GAUSS_514["GAUSS_51400"] % cmd
+ "\nOutput:%s" % output)
upgradeBakPath = self.__getBackupDir()
try:
# backup upgrade_version
oldUpgradeVersionFile = "%s/old_upgrade_version" % upgradeBakPath
cmd = "cp -p %s %s" % (commonUpgradeVersionFile,
oldUpgradeVersionFile)
(status, output) = subprocess.getstatusoutput(cmd)
if (status != 0):
raise Exception(ErrorCode.GAUSS_514["GAUSS_51400"] % cmd
+ "\nOutput:%s" % output)
except Exception as e:
g_logger.debug("Backup failed.ERROR:%s\nClean backup path."
% str(e))
if (os.path.isdir(upgradeBakPath)):
FileUtil.removeDirectory(upgradeBakPath)
def __checkBackupDir(self):
"""
for binary upgrade, Check if backup dir exists, it may be not empty,
because in the second time, we may have
file record app dir and record node app
INPUT:NA
OUTPUT:NA
HIDEN:
1.paths need to be baked
2.100M
PRECONDITION:
POSTCONDITION:
2.for binary upgrade, bak dir has been ready
TEST:
Pseudocode:
"""
binaryBakDir = "%s/binary_upgrade" % EnvUtil.getTmpDirFromEnv()
if not os.path.isdir(binaryBakDir):
os.makedirs(binaryBakDir, ConstantsBase.KEY_DIRECTORY_PERMISSION)
vfs = os.statvfs(binaryBakDir)
availableSize = vfs.f_bavail * vfs.f_bsize / (1024 * 1024)
g_logger.debug("The available size of backup directory: %d M."
% availableSize)
if(availableSize < Const.MAX_APP_SIZE):
g_logger.logExit(ErrorCode.GAUSS_504["GAUSS_50400"]
% ("BakDir", "%dM" % Const.MAX_APP_SIZE))
def __checkDataDir(self):
"""
function: check data directory access rights.
input: NA
output:NA
"""
g_logger.debug("Checking data directory access rights.")
instDirs = self.getNodeDirs()
for path in instDirs:
if (not os.path.exists(path)):
g_logger.logExit(ErrorCode.GAUSS_502["GAUSS_50201"] % path)
if not FileUtil.checkDirWriteable(path):
g_logger.logExit(ErrorCode.GAUSS_502["GAUSS_50205"] % path)
g_logger.debug("Successfully to check data directory access rights.")
def getNodeDirs(self, pathType=""):
"""
function: get the install path and data path of cluster
1. collect install path
2. collect data path
3. collect tablespc path
4. remove the same items
input : pathType
output : tempPaths
"""
localHost = NetUtil.GetHostIpOrName()
dbNode = g_clusterInfo.getDbNodeByName(localHost)
if not dbNode:
g_logger.logExit(ErrorCode.GAUSS_512["GAUSS_51209"]
% ("NODE", localHost))
newNodePaths = []
DnInfos = []
tablespacePaths = []
# collect install path
newNodePaths.append(g_clusterInfo.appPath)
for instance in dbNode.datanodes:
newNodePaths.append(instance.datadir)
if (instance.instanceType != DUMMY_STANDBY_INSTANCE):
DnInfos.append(instance.datadir)
if ('ssdDir' in dir(instance)):
if (len(instance.ssdDir) != 0):
newNodePaths.append(instance.ssdDir)
# collect tablespc path
for instanceDir in DnInfos:
if (not os.path.exists("%s/pg_tblspc" % instanceDir)):
g_logger.debug("%s/pg_tblspc does not exist." % instanceDir)
continue
fileList = os.listdir("%s/pg_tblspc" % instanceDir)
if (len(fileList)):
for filename in fileList:
if (os.path.islink("%s/pg_tblspc/%s"
% (instanceDir, filename))):
linkDir = os.readlink("%s/pg_tblspc/%s"
% (instanceDir, filename))
if (os.path.isdir(linkDir)):
tablespacePaths.append(linkDir)
else:
g_logger.debug("%s is not a link directory."
% filename)
else:
g_logger.debug("%s is not a link file." % filename)
else:
g_logger.debug("%s/pg_tblspc is empty." % instanceDir)
if (pathType == "tablespace"):
tempPaths = tablespacePaths
else:
tempPaths = newNodePaths + tablespacePaths
# remove the same items
tempPaths = list(set(tempPaths))
return tempPaths
def usage():
"""
Usage:
python3 CheckUpgrade.py -t action -R installpath -N newClusterInstallPath
[-U user] [-l log]
Common options:
-t the type of action
-l the path of log file
--help show this help, then exit
Options for big version upgrade check
-U the user of old cluster
-X path of the XML configuration file
Options for upgrade check
-R the install path of old cluster
-N the install path of new cluster
-v backup upgrade version
"""
print(usage.__doc__)
def parseCommandLine():
"""
function: Parse command line and save to global variable
input: NA
output: NA
"""
try:
opts, args = getopt.getopt(sys.argv[1:], "t:R:U:v:l:X:N:", ["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]))
for (key, value) in opts:
if (key == "--help"):
usage()
sys.exit(0)
elif (key == "-t"):
g_opts.action = value
elif (key == "-R"):
g_opts.appPath = value
elif (key == "-U"):
g_opts.user = value
elif (key == "-l"):
g_opts.logFile = os.path.realpath(value)
elif (key == "-X"):
g_opts.xmlFile = os.path.realpath(value)
elif (key == "-v"):
g_opts.upgrade_version = value
elif (key == "-N"):
g_opts.newAppPath = value
else:
GaussLog.exitWithError(ErrorCode.GAUSS_500["GAUSS_50000"] % key)
Parameter.checkParaVaild(key, value)
def checkParameter():
"""
function: Parse command line and save to global variable
input: NA
output: NA
"""
# only check need parameter, just ignore no need parameter
if (g_opts.user == ""):
g_opts.user = pwd.getpwuid(os.getuid()).pw_name
if (g_opts.logFile == ""):
g_opts.logFile = ClusterLog.getOMLogPath(
ClusterConstants.LOCAL_LOG_FILE, "", g_opts.appPath, "")
if g_opts.action in [Const.ACTION_LARGE_UPGRADE,
Const.ACTION_SMALL_UPGRADE,
Const.ACTION_INPLACE_UPGRADE]:
if (g_opts.appPath == ""):
GaussLog.exitWithError(ErrorCode.GAUSS_500["GAUSS_50001"]
% "R" + ".")
elif(g_opts.action == Const.ACTION_CHECK_VERSION):
if(g_opts.upgrade_version == ""):
GaussLog.exitWithError(ErrorCode.GAUSS_500["GAUSS_50001"]
% "v" + ".")
else:
GaussLog.exitWithError(ErrorCode.GAUSS_500["GAUSS_50004"] % 't'
+ " Value: %s." % g_opts.action)
def checkVersion():
"""
function: check version information
input: NA
output: NA
"""
g_logger.debug("Checking version information.")
gaussHome = ClusterDir.getInstallDir(g_opts.user)
if gaussHome == "":
raise Exception(ErrorCode.GAUSS_518["GAUSS_51800"] % "$GAUSSHOME")
localPostgresVersion = \
VersionInfo.getAppBVersion(os.path.realpath(gaussHome))
if (localPostgresVersion.find(g_opts.upgrade_version) > 0):
g_logger.debug("Successfully checked version information.")
else:
raise Exception(ErrorCode.GAUSS_529["GAUSS_52935"])
class OldVersionModules():
"""
Class for providing some functions to apply old version cluster
"""
def __init__(self):
'''
Constructor
'''
self.oldDbClusterInfoModule = None
self.oldDbClusterStatusModule = None
def initGlobalInfos():
"""
function: init global infos
input: NA
output: NA
"""
global g_logger
global g_clusterInfo
g_logger = GaussLog(g_opts.logFile, "CheckUpgrade")
try:
if g_opts.action in [Const.ACTION_CHECK_VERSION]:
g_logger.log("No need to init cluster info under action %s"
% g_opts.action)
return
g_clusterInfo = dbClusterInfo()
if g_opts.xmlFile == "" or not os.path.exists(g_opts.xmlFile):
if g_opts.appPath == "" or not os.path.exists(g_opts.appPath):
raise Exception(ErrorCode.GAUSS_500["GAUSS_50001"] % "R")
staticConfigFile = "%s/bin/cluster_static_config" % g_opts.appPath
g_clusterInfo.initFromStaticConfig(g_opts.user, staticConfigFile)
else:
g_clusterInfo.initFromXml(g_opts.xmlFile)
except Exception as e:
g_logger.log(traceback.format_exc())
g_logger.logExit(str(e))
if __name__ == '__main__':
"""
main function
1. parse command
2. check other parameter
3. init global infos
4. check version information
5. Check application setting for upgrade
"""
try:
g_opts = CmdOptions()
# 1. parse command
parseCommandLine()
# 2. check other parameter
checkParameter()
# 3. init global infos
initGlobalInfos()
except Exception as e:
GaussLog.exitWithError(str(e) + traceback.format_exc())
try:
# 4. check version information
if(g_opts.action == Const.ACTION_CHECK_VERSION):
checkVersion()
else:
# 5. Check application setting for upgrade
g_logger.log("Checking upgraded environment.")
checker = CheckUpgrade(g_opts.appPath, g_opts.action,
g_opts.newAppPath)
checker.run()
g_logger.log("Successfully checked upgraded environment.")
g_logger.closeLog()
except Exception as e:
g_logger.log(traceback.format_exc())
g_logger.logExit(str(e))
sys.exit(0)