390 lines
15 KiB
Python
390 lines
15 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 : gs_postuninstall is a utility to clean up the environment
|
|
# after uninstalling a Gauss200 server.
|
|
#############################################################################
|
|
|
|
import os, sys
|
|
import subprocess
|
|
import grp
|
|
import pwd
|
|
|
|
package_path = os.path.dirname(os.path.realpath(__file__))
|
|
ld_path = package_path + "/gspylib/clib"
|
|
if 'LD_LIBRARY_PATH' not in os.environ:
|
|
os.environ['LD_LIBRARY_PATH'] = ld_path
|
|
os.execve(os.path.realpath(__file__), sys.argv, os.environ)
|
|
if not os.environ.get('LD_LIBRARY_PATH').startswith(ld_path):
|
|
os.environ['LD_LIBRARY_PATH'] = \
|
|
ld_path + ":" + os.environ['LD_LIBRARY_PATH']
|
|
os.execve(os.path.realpath(__file__), sys.argv, os.environ)
|
|
|
|
|
|
from gspylib.common.GaussLog import GaussLog
|
|
from gspylib.common.Common import DefaultValue
|
|
from gspylib.common.ErrorCode import ErrorCode
|
|
from gspylib.common.ParallelBaseOM import ParallelBaseOM
|
|
from gspylib.common.ParameterParsecheck import Parameter
|
|
from impl.postuninstall.OLAP.PostUninstallImplOLAP import \
|
|
PostUninstallImplOLAP
|
|
from domain_utils.cluster_file.cluster_config_file import ClusterConfigFile
|
|
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.net_util import NetUtil
|
|
from domain_utils.domain_common.cluster_constants import ClusterConstants
|
|
from os_platform.linux_distro import LinuxDistro
|
|
from domain_utils.cluster_os.cluster_user import ClusterUser
|
|
|
|
|
|
class Postuninstall(ParallelBaseOM):
|
|
"""
|
|
init the command options
|
|
input : NA
|
|
output: NA
|
|
"""
|
|
|
|
def __init__(self):
|
|
"""
|
|
function: init parameters
|
|
input : NA
|
|
output: NA
|
|
"""
|
|
ParallelBaseOM.__init__(self)
|
|
self.deleteUser = False
|
|
self.deleteGroup = False
|
|
self.clean_gphome = False
|
|
self.clean_host = []
|
|
self.sshpwd = ""
|
|
self.nodeList = []
|
|
self.clusterToolPath = ""
|
|
self.userHome = ""
|
|
self.rootPasswd = ""
|
|
self.ips = []
|
|
self.root_ssh_agent_flag = False
|
|
|
|
def usage(self):
|
|
"""
|
|
gs_postuninstall is a utility to clean up the environment
|
|
after uninstalling the cluster.
|
|
|
|
Usage:
|
|
gs_postuninstall -? |--help
|
|
gs_postuninstall -V |--version
|
|
gs_postuninstall -U USER -X XMLFILE [-L] [--delete-user] [--delete-group]
|
|
[-l LOGFILE]
|
|
|
|
General options:
|
|
-U Cluster user.
|
|
-X Path of the XML configuration file.
|
|
-L Only clean up local nodes.
|
|
--delete-user Delete the OS user.
|
|
--delete-group Delete the group of the OS user.
|
|
-l Path of log file.
|
|
-?, --help Show help information for this utility,
|
|
and exit the command line mode.
|
|
-V, --version Show version information.
|
|
"""
|
|
print(self.usage.__doc__)
|
|
|
|
def parseCommandLine(self):
|
|
"""
|
|
function: Parse command line and save to global variable
|
|
input : NA
|
|
output: NA
|
|
"""
|
|
ParaObj = Parameter()
|
|
ParaDict = ParaObj.ParameterCommandLine("postuninstall")
|
|
# check if has '--help' parameter
|
|
if (ParaDict.__contains__("helpFlag")):
|
|
self.usage()
|
|
sys.exit(0)
|
|
|
|
# check the parameters of postuninstall command
|
|
if (ParaDict.__contains__("user")):
|
|
self.user = ParaDict.get("user")
|
|
if (ParaDict.__contains__("confFile")):
|
|
self.xmlFile = ParaDict.get("confFile")
|
|
if (ParaDict.__contains__("logFile")):
|
|
self.logFile = ParaDict.get("logFile")
|
|
|
|
if (ParaDict.__contains__("delete-user")):
|
|
self.deleteUser = ParaDict.get("delete-user")
|
|
if (ParaDict.__contains__("delete-group")):
|
|
self.deleteGroup = ParaDict.get("delete-group")
|
|
if (ParaDict.__contains__("clean-gphome")):
|
|
self.clean_gphome = ParaDict.get("clean-gphome")
|
|
if (ParaDict.__contains__("nodename")):
|
|
if not "HOST_IP" in os.environ.keys():
|
|
GaussLog.exitWithError(
|
|
ErrorCode.GAUSS_518["GAUSS_51801"] % "HOST_IP doesn't" +
|
|
" so -h parameter is not needed.")
|
|
self.clean_host = ParaDict.get("nodename")
|
|
if len(self.clean_host) == 0:
|
|
raise Exception(ErrorCode.GAUSS_500["GAUSS_50004"] % 'h')
|
|
|
|
if (ParaDict.__contains__("localMode")):
|
|
self.localMode = ParaDict.get("localMode")
|
|
|
|
if "HOST_IP" in os.environ.keys():
|
|
if not ParaDict.__contains__("localMode"):
|
|
if not (ParaDict.__contains__("clean-gphome")
|
|
and ParaDict.__contains__("nodename")):
|
|
GaussLog.exitWithError(
|
|
ErrorCode.GAUSS_518["GAUSS_51801"] % "HOST_IP" +
|
|
" so you must specify the -L parameter or (-h and "
|
|
"--clean-gphome) parameters.")
|
|
if ParaDict.__contains__("clean-gphome"):
|
|
if ParaDict.__contains__("localMode") and\
|
|
ParaDict.__contains__("nodename"):
|
|
GaussLog.exitWithError(ErrorCode.GAUSS_500["GAUSS_50005"]
|
|
% ("-L", "-h"))
|
|
|
|
if (self.deleteGroup == True and self.deleteUser != True):
|
|
GaussLog.exitWithError(ErrorCode.GAUSS_500["GAUSS_50001"]
|
|
% "-delete-user" + ".")
|
|
|
|
def checkParameter(self):
|
|
"""
|
|
function: check parameter
|
|
input : NA
|
|
output: NA
|
|
"""
|
|
# check user
|
|
self.checkUser()
|
|
# check config file
|
|
ClusterConfigFile.checkConfigFile(self.xmlFile)
|
|
# check log file
|
|
self.logFile = ClusterLog.checkLogFile(self.logFile, self.user, self.xmlFile,
|
|
ClusterConstants.UNPREINSTALL_LOG_FILE)
|
|
# check mpprc file if needed, should be done
|
|
# before check preinstall step
|
|
self.checkMpprcFile()
|
|
# check preInstall
|
|
self.checkPreInstall()
|
|
# check group for redhat
|
|
self.checkGroup()
|
|
|
|
def checkUser(self):
|
|
"""
|
|
function: check the user
|
|
input : NA
|
|
output: NA
|
|
"""
|
|
# check if no user
|
|
if (self.user == ""):
|
|
GaussLog.exitWithError(ErrorCode.GAUSS_500["GAUSS_50001"] % "U"
|
|
+ ".")
|
|
# check if is root user
|
|
if (self.user == "root"):
|
|
GaussLog.exitWithError(ErrorCode.GAUSS_503["GAUSS_50301"])
|
|
|
|
try:
|
|
ClusterUser.checkUser(self.user, False)
|
|
except Exception as e:
|
|
GaussLog.exitWithError(str(e))
|
|
|
|
if (pwd.getpwnam(self.user).pw_uid == 0):
|
|
GaussLog.exitWithError(ErrorCode.GAUSS_503["GAUSS_50302"])
|
|
|
|
|
|
def checkMpprcFile(self):
|
|
"""
|
|
function: check MpprcFile
|
|
input : NA
|
|
output: NA
|
|
"""
|
|
# get path of MpprcFile
|
|
self.mpprcFile = EnvUtil.getEnv(DefaultValue.MPPRC_FILE_ENV)
|
|
|
|
try:
|
|
# get tool path
|
|
self.clusterToolPath = ClusterDir.getPreClusterToolPath(self.xmlFile)
|
|
except Exception as e:
|
|
GaussLog.exitWithError(str(e))
|
|
# if MpprcFile is null
|
|
if (self.mpprcFile == None):
|
|
self.mpprcFile = ""
|
|
# if MpprcFile is not null
|
|
if (self.mpprcFile != ""):
|
|
# if no MpprcFile
|
|
if (not os.path.exists(self.mpprcFile)):
|
|
GaussLog.exitWithError(ErrorCode.GAUSS_502["GAUSS_50201"]
|
|
% "MPPRC file" + " %s."
|
|
% self.mpprcFile)
|
|
# if is not absolute path
|
|
if (not os.path.isabs(self.mpprcFile)):
|
|
GaussLog.exitWithError(ErrorCode.GAUSS_512["GAUSS_51206"]
|
|
% self.mpprcFile)
|
|
|
|
def checkPreInstall(self):
|
|
"""
|
|
function: check preInstall
|
|
input : NA
|
|
output: NA
|
|
"""
|
|
# check if agent-mode
|
|
if "HOST_IP" in os.environ.keys():
|
|
# get om_agent path
|
|
agent_path_cmd = "ps aux | grep 'om_agent.py' | grep %s | grep " \
|
|
"-v grep | head -n 1 | awk '{print $NF}'" % \
|
|
self.user
|
|
(status, output) = subprocess.getstatusoutput(agent_path_cmd)
|
|
if (status != 0):
|
|
raise Exception(ErrorCode.GAUSS_535["GAUSS_53507"]
|
|
% agent_path_cmd)
|
|
agent_path = os.path.dirname(output.strip())
|
|
agent_conf_file = os.path.join(agent_path, 'om_agent.conf')
|
|
if not os.path.exists(agent_conf_file):
|
|
raise Exception(ErrorCode.GAUSS_502["GAUSS_50201"]
|
|
% agent_conf_file)
|
|
|
|
# get agent sep_env_file
|
|
with open(agent_conf_file) as fp:
|
|
recordLines = fp.readlines()
|
|
sep_env_file = ""
|
|
for tmp in recordLines:
|
|
if 'sep_env_file' in tmp:
|
|
sep_env_file = tmp.split("=")[-1].strip()
|
|
if not os.path.exists(sep_env_file):
|
|
raise Exception(
|
|
ErrorCode.GAUSS_502["GAUSS_50201"] % sep_env_file)
|
|
|
|
cmd = "su - %s -c 'source %s && echo $GAUSS_ENV' 2>/dev/null"\
|
|
% (self.user, sep_env_file)
|
|
(status, output) = subprocess.getstatusoutput(cmd)
|
|
if (status != 0):
|
|
GaussLog.exitWithError(ErrorCode.GAUSS_518["GAUSS_51802"]
|
|
% "$GAUSS_ENV" + "Error: \n%s." % output
|
|
+ "The cmd is %s" % cmd)
|
|
gaussEnv = output.strip()
|
|
else:
|
|
# check if has mpprcFile
|
|
if (self.mpprcFile != ""):
|
|
userprofile = self.mpprcFile
|
|
else:
|
|
userprofile = "/home/%s/.bashrc" % self.user
|
|
|
|
cmd = "su - %s -c 'source %s && echo $GAUSS_ENV' 2>/dev/null"\
|
|
% (self.user, userprofile)
|
|
(status, output) = subprocess.getstatusoutput(cmd)
|
|
if (status != 0):
|
|
GaussLog.exitWithError(ErrorCode.GAUSS_518["GAUSS_51802"]
|
|
% "$GAUSS_ENV" + "Error: \n%s." % output
|
|
+ "The cmd is %s" % cmd)
|
|
gaussEnv = output.strip()
|
|
|
|
# if gaussEnv is 2, user do not do uninstall before
|
|
if (str(gaussEnv) == "2"):
|
|
GaussLog.exitWithError(ErrorCode.GAUSS_525["GAUSS_52501"]
|
|
% "gs_uninstall")
|
|
# if gaussEnv is not 1, user do not do preinstall before
|
|
elif (str(gaussEnv) != "1" and not self.clean_gphome):
|
|
GaussLog.exitWithError(
|
|
ErrorCode.GAUSS_525["GAUSS_52501"] % "gs_preinstall" +
|
|
"If you do preinstall with seperate file mode, please input "
|
|
"sep-env-file before postuninstall. ")
|
|
elif (str(gaussEnv) == "1" or str(gaussEnv) == "2")\
|
|
and self.clean_gphome:
|
|
GaussLog.exitWithError(ErrorCode.GAUSS_525["GAUSS_52501"]
|
|
% "'gs_uninstall' or 'gs_postuninstall"
|
|
" no clean gphome'")
|
|
|
|
def checkGroup(self):
|
|
"""
|
|
function: check user group
|
|
input : NA
|
|
output: NA
|
|
"""
|
|
try:
|
|
# get user group
|
|
group = grp.getgrgid(pwd.getpwnam(self.user).pw_gid).gr_name
|
|
distname, version, idnum = LinuxDistro.linux_distribution()
|
|
# check if OS version is redhat or Euler
|
|
if (distname in ("redhat", "euleros", "centos", "openEuler")):
|
|
if (self.deleteGroup != True and self.deleteUser == True
|
|
and self.user == group):
|
|
GaussLog.exitWithError(ErrorCode.GAUSS_500["GAUSS_50001"] %
|
|
"-delete-group" + ". You must "
|
|
"delete the "
|
|
"group when you "
|
|
"delete the "
|
|
"user which has "
|
|
"the same name "
|
|
"with the group "
|
|
"in redhat.")
|
|
except Exception as e:
|
|
GaussLog.exitWithError(ErrorCode.GAUSS_503["GAUSS_50308"]
|
|
+ "Failed to obtain the group for %s" %
|
|
self.user + "Error:\n%s" % str(e))
|
|
|
|
def initGlobals(self):
|
|
"""
|
|
function: init Logg file
|
|
input : NA
|
|
output: NA
|
|
"""
|
|
self.initLogger("gs_postuninstall")
|
|
self.logger.ignoreErr = True
|
|
|
|
try:
|
|
self.logger.log("Parsing the configuration file.", "addStep")
|
|
# get cluster info from xml file
|
|
# Initialize the self.clusterInfo variable
|
|
self.initClusterInfo()
|
|
# Initialize the self.sshTool variable
|
|
self.initSshTool(self.clusterInfo.getClusterNodeNames(),
|
|
DefaultValue.TIMEOUT_PSSH_POSTPREINSTALL)
|
|
self.logger.debug("The cluster's information:\n%s."
|
|
% str(self.clusterInfo))
|
|
self.logger.log("Successfully parsed the configuration file.",
|
|
"constant")
|
|
except Exception as e:
|
|
self.logger.logExit(str(e))
|
|
|
|
dirName = os.path.dirname(self.logFile)
|
|
self.localLog = os.path.join(dirName, ClusterConstants.LOCAL_LOG_FILE)
|
|
self.userHome = DefaultValue.getUserHome(self.user)
|
|
|
|
if __name__ == '__main__':
|
|
"""
|
|
main function
|
|
input : NA
|
|
output: NA
|
|
"""
|
|
if (os.getuid() != 0):
|
|
GaussLog.exitWithError(ErrorCode.GAUSS_501["GAUSS_50104"])
|
|
|
|
try:
|
|
postuninstall = Postuninstall()
|
|
postuninstall.parseCommandLine()
|
|
postuninstall.checkParameter()
|
|
postuninstall.initGlobals()
|
|
|
|
if len(postuninstall.clusterInfo.getClusterNodeNames()) == 1 and \
|
|
postuninstall.clusterInfo.getClusterNodeNames()[
|
|
0] == NetUtil.GetHostIpOrName():
|
|
postuninstall.localMode = True
|
|
impl = PostUninstallImplOLAP(postuninstall)
|
|
|
|
# Perform the whole extand process
|
|
impl.run()
|
|
except Exception as e:
|
|
GaussLog.exitWithError(str(e))
|