Files
openGauss-OM/script/impl/uninstall/UninstallImpl.py
2022-11-07 20:17:20 +08:00

469 lines
18 KiB
Python

# -*- 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 sys
import subprocess
import time
import os
sys.path.append(sys.path[0] + "/../")
from gspylib.common.Common import DefaultValue, ClusterCommand
from gspylib.common.OMCommand import OMCommand
from gspylib.common.ErrorCode import ErrorCode
from gspylib.os.gsfile import g_file
from base_utils.executor.cmd_executor import CmdExecutor
from domain_utils.cluster_file.cluster_dir import ClusterDir
from base_utils.os.env_util import EnvUtil
from base_utils.os.file_util import FileUtil
from base_utils.os.net_util import NetUtil
class UninstallImpl:
"""
init the command options
save command line parameter values
"""
def __init__(self, unstallation):
"""
function: constructor
"""
self.logFile = unstallation.logFile
self.cleanInstance = unstallation.cleanInstance
self.localLog = unstallation.localLog
self.user = unstallation.user
self.group = unstallation.group
self.mpprcFile = unstallation.mpprcFile
self.localMode = unstallation.localMode
self.logger = unstallation.logger
self.sshTool = unstallation.sshTool
self.tmpDir = EnvUtil.getTmpDirFromEnv(self.user)
try:
# Initialize the unstallation.clusterInfo variable
unstallation.initClusterInfoFromStaticFile(self.user)
self.clusterInfo = unstallation.clusterInfo
nodeNames = self.clusterInfo.getClusterNodeNames()
# Initialize the self.sshTool variable
unstallation.initSshTool(nodeNames,
DefaultValue.TIMEOUT_PSSH_UNINSTALL)
self.sshTool = unstallation.sshTool
except Exception as e:
self.logger.logExit(str(e))
def checkLogFilePath(self):
"""
function: Check log file path
input : NA
output: NA
"""
clusterPath = []
try:
# get tool path
clusterPath.append(ClusterDir.getClusterToolPath(self.user))
# get tmp path
tmpDir = EnvUtil.getTmpDirFromEnv()
clusterPath.append(tmpDir)
# get cluster path
hostName = NetUtil.GetHostIpOrName()
dirs = self.clusterInfo.getClusterDirectorys(hostName, False)
# loop all cluster path
for checkdir in dirs.values():
clusterPath.extend(checkdir)
self.logger.debug("Cluster paths %s." % clusterPath)
# check directory
FileUtil.checkIsInDirectory(self.logFile, clusterPath)
except Exception as e:
self.logger.logExit(str(e))
def checkUninstall(self):
"""
function: Check uninstall
input : NA
output: NA
"""
# Checking uninstallation
self.logger.log("Checking uninstallation.", "addStep")
# use check uninstall to check every nodes
cmd = "%s -R '%s' -U %s -l %s" % (
OMCommand.getLocalScript("Local_Check_Uninstall"),
self.clusterInfo.appPath, self.user, self.localLog)
# check if need to clean instance
if (self.cleanInstance):
cmd += " -d"
self.logger.debug("Command for checking uninstallation: " + cmd)
CmdExecutor.execCommandWithMode(cmd,
self.sshTool, self.localMode,
self.mpprcFile)
self.logger.log("Successfully checked uninstallation.", "constant")
def cm_stop_cluster(self):
"""
Stop cluster with CM
"""
# get stop command, if node_id is not zero, then only stop local node
node_id = 0
cmd = ClusterCommand.getStopCmd(node_id, "i")
if self.localMode:
local_node_list = [node for node in self.clusterInfo.dbNodes
if node.name == NetUtil.GetHostIpOrName()]
if not local_node_list:
self.logger.logExit(ErrorCode.GAUSS_516["GAUSS_51610"] % "the cluster" +
" Error:\nLocal node is not in the static file.")
cmd = ClusterCommand.getStopCmd(local_node_list[0].id, "i")
(status, output) = subprocess.getstatusoutput(cmd)
# if do command fail, throw error
if status != 0:
self.logger.logExit(ErrorCode.GAUSS_516["GAUSS_51610"] % "the cluster" +
" Error:\n%s" % output)
if self.localMode:
self.logger.log("Successfully stopped local node.", "constant")
else:
self.logger.log("Successfully stopped the cluster.", "constant")
# check and kill all processes about
# clean cm_agent,cm_server,gs_gtm,gaussdb(CN/DN) and etcd.
self.logger.debug("Checking and killing processes.", "addStep")
# local mode, kill all process in local node
if self.localMode:
for prog_name in ["cm_agent", "cm_server", "gaussdb",
"CheckDataDiskUsage"]:
DefaultValue.KillAllProcess(self.user, prog_name)
# kill process in all nodes
else:
cm_agent_file = "%s/bin/cm_agent" % self.clusterInfo.appPath
cm_server_file = "%s/bin/cm_server" % self.clusterInfo.appPath
gaussdb_file = "%s/bin/gaussdb" % self.clusterInfo.appPath
check_file = "CheckDataDiskUsage"
for prog_name in [cm_agent_file, cm_server_file, gaussdb_file,
check_file]:
self.CheckAndKillAliveProc(prog_name)
self.logger.debug("Successfully checked and killed processes.", "constant")
def StopCluster(self):
"""
function: Stopping the cluster
input : NA
output: NA
"""
self.logger.log("Stopping the cluster.", "addStep")
# get the static config
static_config = \
"%s/bin/cluster_static_config" % self.clusterInfo.appPath
static_config_bak = \
"%s/bin/cluster_static_config_bak" % self.clusterInfo.appPath
# if cluster_static_config_bak exists
# and static_config does not exists, mv it to static_config
if (not os.path.exists(static_config) and os.path.exists(
static_config_bak)):
cmd = "mv %s %s" % (static_config_bak, static_config)
(status, output) = subprocess.getstatusoutput(cmd)
if (status != 0):
self.logger.debug("The cmd is %s " % cmd)
self.logger.error("rename cluster_static_config_bak failed")
self.logger.debug("Error:\n%s" % output)
# if path not exits, can not stop cluster
if not os.path.exists(static_config):
self.logger.debug("Failed to stop the cluster.", "constant")
return
if DefaultValue.get_cm_server_num_from_static(self.clusterInfo) == 0:
# Stop cluster applications
cmd = "source %s; %s -U %s -R %s -l %s" % (
self.mpprcFile, OMCommand.getLocalScript("Local_StopInstance"),
self.user, self.clusterInfo.appPath, self.localLog)
self.logger.debug("Command for stop cluster: %s" % cmd)
CmdExecutor.execCommandWithMode(cmd, self.sshTool,
self.localMode, self.mpprcFile)
self.logger.log("Successfully stopped the cluster.")
else:
self.cm_stop_cluster()
def CheckAndKillAliveProc(self, procFileName):
"""
function: When uninstall gaussdb cluster. After it is stopped,
We must make sure that all process
about gaussdb cluster have been stopped. Not including
om_monitor.
input : procFileName
output: NA
"""
try:
failedNodes = []
validNodeName = self.clusterInfo.getClusterNodeNames()
# the command for killing all process
cmd_check_kill = DefaultValue.killInstProcessCmd(procFileName,
True, 9, False)
# use sshTool to kill process in all nodes
(status, output) = self.sshTool.getSshStatusOutput(cmd_check_kill,
validNodeName)
# get the node which not be killed
for node in validNodeName:
if (status[node] != DefaultValue.SUCCESS):
failedNodes.append(node)
# kill process in nodes again
if (len(failedNodes)):
time.sleep(1)
(status, output) = self.sshTool.getSshStatusOutput(
cmd_check_kill, failedNodes)
for node in failedNodes:
# if still fail, throw error
if (status[node] != DefaultValue.SUCCESS):
raise Exception(output)
except Exception as e:
raise Exception(str(e))
def CleanInstance(self):
"""
function: clean instance
input : NA
output : NA
"""
self.logger.debug("Deleting instance.", "addStep")
# check if need delete instance
if (not self.cleanInstance):
self.logger.debug("No need to delete data.", "constant")
return
# Clean instance data
cmd = "%s -U %s -l %s" % (
OMCommand.getLocalScript("Local_Clean_Instance"), self.user,
self.localLog)
self.logger.debug("Command for deleting instance: %s" % cmd)
CmdExecutor.execCommandWithMode(cmd,
self.sshTool, self.localMode,
self.mpprcFile)
# clean upgrade temp backup path
upgrade_bak_dir = ClusterDir.getBackupDir("upgrade", self.user)
cmd = g_file.SHELL_CMD_DICT["cleanDir"] % (
upgrade_bak_dir, upgrade_bak_dir, upgrade_bak_dir)
CmdExecutor.execCommandWithMode(cmd,
self.sshTool, self.localMode,
self.mpprcFile)
self.logger.log("Successfully deleted instances.", "constant")
def CleanTmpFiles(self):
"""
function: clean temp files
input : NA
output: NA
"""
self.logger.debug("Deleting temporary files.", "addStep")
try:
# copy record_app_directory file
tmpDir = EnvUtil.getTmpDirFromEnv(self.user)
if tmpDir == "":
raise Exception(ErrorCode.GAUSS_518["GAUSS_51800"] % "$PGHOST")
upgradeBackupPath = os.path.join(tmpDir, "binary_upgrade")
copyPath = os.path.join(upgradeBackupPath, "record_app_directory")
appPath = ClusterDir.getInstallDir(self.user)
if appPath == "":
raise Exception(ErrorCode.GAUSS_518["GAUSS_51800"] % "$PGHOST")
if copyPath != "":
copyCmd = "(if [ -f '%s' ];then cp -f -p '%s' '%s/';fi)" % (
copyPath, copyPath, appPath)
CmdExecutor.execCommandWithMode(
copyCmd,
self.sshTool, self.localMode,
self.mpprcFile)
cmd = g_file.SHELL_CMD_DICT["cleanDir"] % (
self.tmpDir, self.tmpDir, self.tmpDir)
# clean dir of PGHOST
CmdExecutor.execCommandWithMode(cmd,
self.sshTool, self.localMode,
self.mpprcFile)
except Exception as e:
self.logger.logExit(str(e))
self.logger.debug("Successfully deleted temporary files.", "constant")
def UninstallApp(self):
"""
function: Uninstall application
input : NA
output: NA
"""
self.logger.log("Uninstalling application.", "addStep")
cmd = "%s -R '%s' -U %s -l %s -T" % (
OMCommand.getLocalScript("Local_Uninstall"),
self.clusterInfo.appPath,
self.user, self.localLog)
self.logger.debug("Command for Uninstalling: %s" % cmd)
# clean application
CmdExecutor.execCommandWithMode(cmd,
self.sshTool, self.localMode,
self.mpprcFile)
self.logger.log("Successfully uninstalled application.", "constant")
def CleanStaticConfFile(self):
"""
function: clean static conf file
input : NA
output: NA
"""
self.logger.debug("Deleting static configuration file.", "addStep")
try:
cmd = "rm -rf '%s'/bin " % self.clusterInfo.appPath
# delete bin dir in GAUSSHOME
CmdExecutor.execCommandWithMode(
cmd,
self.sshTool, self.localMode,
self.mpprcFile)
except Exception as e:
self.logger.exitWithError(str(e))
self.logger.debug("Successfully deleted static configuration file.",
"constant")
def CleanRackFile(self):
"""
function: clean rack information file
input : NA
output: NA
"""
gp_home = EnvUtil.getEnv("GPHOME")
if os.path.exists(gp_home):
gp_home = os.path.realpath(gp_home)
rack_conf_file = os.path.realpath(
os.path.join(gp_home, "script/gspylib/etc/conf/rack_info.conf"))
if os.path.isfile(rack_conf_file):
cmd = "rm -f %s" % rack_conf_file
CmdExecutor.execCommandWithMode(cmd,
self.sshTool, self.localMode,
mpprc_file=self.mpprcFile)
self.logger.debug("Successfully deleted rack information file.")
def clean_dss_home(self):
"""
function: Clean default log
input : NA
output: NA
"""
self.logger.debug("Deleting dss_home.", "addStep")
# check if need delete instance
if not self.cleanInstance:
self.logger.debug("No need to delete data.", "constant")
return
try:
# clean log
dss_home = EnvUtil.getEnvironmentParameterValue("DSS_HOME", self.user)
cmd = g_file.SHELL_CMD_DICT["cleanDir"] % (
dss_home, dss_home, dss_home)
# delete log dir
CmdExecutor.execCommandWithMode(cmd,
self.sshTool, self.localMode,
self.mpprcFile)
except Exception as e:
self.logger.exitWithError(str(e))
self.logger.debug("Successfully deleted log.", "constant")
def CleanLog(self):
"""
function: Clean default log
input : NA
output: NA
"""
self.logger.debug("Deleting log.", "addStep")
# check if need delete instance
if (not self.cleanInstance):
self.logger.debug("No need to delete data.", "constant")
return
try:
# clean log
userLogDir = ClusterDir.getUserLogDirWithUser(self.user)
cmd = g_file.SHELL_CMD_DICT["cleanDir"] % (
userLogDir, userLogDir, userLogDir)
# delete log dir
CmdExecutor.execCommandWithMode(cmd,
self.sshTool, self.localMode,
self.mpprcFile)
except Exception as e:
self.logger.exitWithError(str(e))
self.logger.debug("Successfully deleted log.", "constant")
def checkEnv(self):
"""
function: check if GAUSS_ENV is 2
input : NA
output: NA
"""
pass
def ReCleanEtcdPath(self):
"""
function: make sure the etcd path is clean.
input : NA
output: NA
"""
pass
def ReKillEtcdProcess(self):
"""
function: make sure the etcd process is clean.
input : NA
output: NA
"""
if (self.localMode):
DefaultValue.KillAllProcess(self.user, "etcd")
# kill process in all nodes
else:
etcd_file = "%s/bin/etcd" % self.clusterInfo.appPath
self.CheckAndKillAliveProc(etcd_file)
def check_drop_node(self):
"""
Check flag file of drop node
"""
flag_file = os.path.realpath(os.path.join(self.clusterInfo.appPath,
"bin", "drop_node_flag"))
if os.path.isfile(flag_file):
self.logger.log("This is a node where the gs_dropnode command has been executed. "
"Uninstall a single node instead of the gs_dropnode command.")
self.localMode = True
def run(self):
"""
function: Uninstall database cluster
input : NA
output: NA
"""
try:
self.checkEnv()
self.checkLogFilePath()
self.check_drop_node()
# do uninstall
self.checkUninstall()
self.StopCluster()
self.CleanInstance()
self.CleanTmpFiles()
self.UninstallApp()
self.ReCleanEtcdPath()
self.ReKillEtcdProcess()
self.logger.closeLog()
self.CleanStaticConfFile()
self.CleanRackFile()
self.clean_dss_home()
self.CleanLog()
self.logger.log("Uninstallation succeeded.")
except Exception as e:
self.logger.logExit(str(e))