1289 lines
57 KiB
Python
1289 lines
57 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.
|
|
# ----------------------------------------------------------------------------
|
|
# Description : gs_om is a utility to manage a Gauss200 cluster.
|
|
#############################################################################
|
|
|
|
import subprocess
|
|
import os
|
|
import sys
|
|
import pwd
|
|
|
|
from datetime import datetime
|
|
import getpass
|
|
|
|
sys.path.append(sys.path[0] + "/../../../")
|
|
from gspylib.common.DbClusterInfo import dbClusterInfo, queryCmd
|
|
from gspylib.threads.SshTool import SshTool
|
|
from gspylib.common.DbClusterStatus import DbClusterStatus
|
|
from gspylib.common.ErrorCode import ErrorCode
|
|
from gspylib.common.Common import DefaultValue, ClusterCommand
|
|
from gspylib.common.OMCommand import OMCommand
|
|
from gspylib.os.gsfile import g_file
|
|
from base_utils.os.cmd_util import CmdUtil
|
|
from base_utils.os.compress_util import CompressUtil
|
|
from base_utils.os.env_util import EnvUtil
|
|
from base_utils.os.file_util import FileUtil
|
|
from base_utils.os.net_util import NetUtil
|
|
from base_utils.os.user_util import UserUtil
|
|
from base_utils.common.constantsbase import ConstantsBase
|
|
from domain_utils.cluster_file.cluster_dir import ClusterDir
|
|
from base_utils.executor.cmd_executor import CmdExecutor
|
|
|
|
# Cert
|
|
EMPTY_CERT = "emptyCert"
|
|
EMPTY_FLAG = "emptyflag"
|
|
|
|
###########################################
|
|
class OmImpl:
|
|
"""
|
|
init the command options
|
|
save command line parameter values
|
|
"""
|
|
|
|
def __init__(self, OperationManager):
|
|
"""
|
|
function: constructor
|
|
"""
|
|
# global
|
|
self.context = OperationManager
|
|
self.logger = OperationManager.logger
|
|
self.user = OperationManager.user
|
|
self.newClusterInfo = None
|
|
self.oldClusterInfo = None
|
|
self.utilsPath = None
|
|
self.mpprcFile = ""
|
|
self.nodeId = OperationManager.g_opts.nodeId
|
|
self.time_out = OperationManager.g_opts.time_out
|
|
self.mode = OperationManager.g_opts.mode
|
|
self.clusterInfo = OperationManager.clusterInfo
|
|
self.dataDir = OperationManager.g_opts.dataDir
|
|
self.sshTool = None
|
|
|
|
def doStopCluster(self):
|
|
"""
|
|
function: do stop cluster
|
|
input: NA
|
|
output: NA
|
|
"""
|
|
pass
|
|
|
|
def doStart(self):
|
|
"""
|
|
function:Start cluster or node
|
|
input:NA
|
|
output:NA
|
|
"""
|
|
self.doStartCluster()
|
|
|
|
def doStop(self):
|
|
"""
|
|
function:Stop cluster or node
|
|
input:NA
|
|
output:NA
|
|
"""
|
|
self.logger.debug("Operating: Stopping.")
|
|
self.doStopCluster()
|
|
|
|
def getNodeStatus(self, nodename):
|
|
"""
|
|
function: get node status
|
|
input: nodename
|
|
output: NA
|
|
"""
|
|
try:
|
|
# Create a temporary file to save cluster status
|
|
tmpDir = EnvUtil.getTmpDirFromEnv()
|
|
tmpFile = os.path.join(tmpDir, "gauss_cluster_status.dat_" + \
|
|
str(datetime.now().strftime(
|
|
'%Y%m%d%H%M%S')) + "_" + str(
|
|
os.getpid()))
|
|
|
|
# Perform the start operation
|
|
# Writes the execution result to a temporary file
|
|
cmd = ClusterCommand.getQueryStatusCmd("", tmpFile, True)
|
|
(status, output) = subprocess.getstatusoutput(cmd)
|
|
if (status != 0):
|
|
self.logger.debug("The cmd is %s " % cmd)
|
|
raise Exception(ErrorCode.GAUSS_514["GAUSS_51400"] % \
|
|
cmd + "Error: \n%s" % output)
|
|
|
|
# Initialize cluster status information for the temporary file
|
|
clusterStatus = DbClusterStatus()
|
|
clusterStatus.initFromFile(tmpFile)
|
|
|
|
# Get node status
|
|
nodeStatusInfo = None
|
|
for dbNode in clusterStatus.dbNodes:
|
|
if (dbNode.name == nodename):
|
|
nodeStatusInfo = dbNode
|
|
if (nodeStatusInfo and nodeStatusInfo.isNodeHealthy()):
|
|
nodeStatus = clusterStatus.OM_NODE_STATUS_NORMAL
|
|
else:
|
|
nodeStatus = clusterStatus.OM_NODE_STATUS_ABNORMAL
|
|
|
|
FileUtil.cleanTmpFile(tmpFile)
|
|
return nodeStatus
|
|
except Exception as e:
|
|
FileUtil.cleanTmpFile(tmpFile)
|
|
self.logger.debug(
|
|
"Failed to get node status. Error: \n%s." % str(e))
|
|
return "Abnormal"
|
|
|
|
def getQueryStatusByCm(self, nodeId):
|
|
"""
|
|
function: query status by cm
|
|
:param nodeId:
|
|
:return:
|
|
"""
|
|
# Call cm_ctl to query the cluster status
|
|
get_cluster_status_cmd = ClusterCommand.getQueryStatusCmdForDisplay(
|
|
nodeId,
|
|
self.context.g_opts.outFile,
|
|
self.context.clusterInfo.clusterType,
|
|
self.context.g_opts.show_detail,
|
|
self.context.g_opts.showAll)
|
|
|
|
if self.context.g_opts.outFile != "":
|
|
get_cluster_status_cmd += "&& chmod %s '%s'" % (
|
|
DefaultValue.KEY_FILE_MODE, self.context.g_opts.outFile)
|
|
# Call cm_ctl to query the cluster status
|
|
(status, output) = subprocess.getstatusoutput(get_cluster_status_cmd)
|
|
if status != 0:
|
|
if not(status == 255 and "Down" in output):
|
|
raise Exception(ErrorCode.GAUSS_516[
|
|
"GAUSS_51600"] + "\nCommand:%s\nError: \n%s" % (
|
|
get_cluster_status_cmd, output))
|
|
node_status_line = ""
|
|
if self.context.g_opts.nodeName != "":
|
|
node_status = self.getNodeStatus(self.context.g_opts.nodeName)
|
|
node_status_line = "node_state : %s\n\n" % node_status + \
|
|
"-----------------------------------------------------------------------\n"
|
|
|
|
# Outputs the check result if no output file is specified
|
|
if self.context.g_opts.outFile == "":
|
|
if status == 0 and self.context.g_opts.show_detail:
|
|
temp_lines = output.splitlines()
|
|
node_head = temp_lines[-3].split("|")[0]
|
|
node_split = "-" * len(node_head)
|
|
node_info = [info.strip() for info in temp_lines[-1].split("|")]
|
|
self.logger.log("\n".join(temp_lines[:-3] + [node_head] + [node_split] +
|
|
node_info))
|
|
else:
|
|
self.logger.log(output)
|
|
if node_status_line:
|
|
self.logger.log(node_status_line)
|
|
else:
|
|
if node_status_line:
|
|
FileUtil.createFileInSafeMode(self.context.g_opts.outFile)
|
|
with open(self.context.g_opts.outFile, "a") as fp:
|
|
fp.write(node_status_line)
|
|
fp.write(os.linesep)
|
|
fp.flush()
|
|
fp.close()
|
|
self.logger.log("Status check is completed.")
|
|
|
|
def getQueryStatusWithoutCm(self, nodeId=0, sshtool=None, hostName=""):
|
|
"""
|
|
function:query status without cm
|
|
:param nodeId:
|
|
:param sshtool:
|
|
:param hostName:
|
|
:return:
|
|
"""
|
|
cmd = queryCmd()
|
|
if self.context.g_opts.outFile != "":
|
|
cmd.outputFile = self.context.g_opts.outFile
|
|
else:
|
|
cmd.outputFile = self.logger.logFile
|
|
if self.context.g_opts.show_detail:
|
|
if (self.context.clusterInfo.clusterType
|
|
== DefaultValue.CLUSTER_TYPE_SINGLE_PRIMARY_MULTI_STANDBY):
|
|
cmd.dataPathQuery = True
|
|
cmd.azNameQuery = True
|
|
else:
|
|
cmd.dataPathQuery = True
|
|
else:
|
|
if nodeId > 0:
|
|
self.context.clusterInfo.queryNodeInfo(sshtool, hostName,
|
|
nodeId, cmd.outputFile)
|
|
return
|
|
az_name = self.context.g_opts.azName
|
|
if az_name:
|
|
self.context.clusterInfo.queryNodeInfo(sshtool, hostName,
|
|
nodeId, cmd.outputFile, az_name)
|
|
return
|
|
if self.context.g_opts.showAll:
|
|
self.context.clusterInfo.queryNodeInfo(sshtool, hostName,
|
|
nodeId, cmd.outputFile)
|
|
return
|
|
cmd.clusterStateQuery = True
|
|
db_nums = len(self.context.clusterInfo.dbNodes)
|
|
ssh_tools = []
|
|
for _ in range(db_nums - 1):
|
|
ssh_tools.append(SshTool([], timeout=self.time_out))
|
|
self.context.clusterInfo.queryClsInfo(hostName, ssh_tools,
|
|
self.context.mpprcFile, cmd)
|
|
def doStatus(self):
|
|
"""
|
|
function:Get the status of cluster or node
|
|
input:NA
|
|
output:NA
|
|
"""
|
|
host_name = NetUtil.GetHostIpOrName()
|
|
sshtool = SshTool(self.context.clusterInfo.getClusterNodeNames(), timeout=self.time_out)
|
|
node_id = 0
|
|
if self.context.g_opts.nodeName != "":
|
|
for db_node in self.context.clusterInfo.dbNodes:
|
|
if db_node.name == self.context.g_opts.nodeName:
|
|
node_id = db_node.id
|
|
if node_id == 0:
|
|
raise Exception(
|
|
ErrorCode.GAUSS_516["GAUSS_51619"]
|
|
% self.context.g_opts.nodeName)
|
|
if ((not self.context.clusterInfo.hasNoCm())
|
|
and DefaultValue.isgreyUpgradeNodeSpecify(self.context.user,
|
|
DefaultValue.GREY_UPGRADE_STEP_UPGRADE_PROCESS, None, self.context.logger)):
|
|
self.getQueryStatusByCm(node_id)
|
|
else:
|
|
self.getQueryStatusWithoutCm(node_id, sshtool, host_name)
|
|
self.logger.debug("Successfully obtained the cluster status.")
|
|
|
|
def change_cluster_info(self):
|
|
temp_change_dic = {}
|
|
for i in range(0, len(self.context.g_opts.old_values)):
|
|
temp_change_dic['90123456789%d' % i] = (self.context.g_opts.old_values[i],
|
|
self.context.g_opts.new_values[i])
|
|
# change old value to middle value
|
|
for key, value in temp_change_dic.items():
|
|
for node in self.context.clusterInfo.dbNodes:
|
|
self.change_node_info(node, key, value[0])
|
|
for inst in node.datanodes:
|
|
self.change_inst_info(inst, key, value[0])
|
|
# change middle value to new value
|
|
for key, value in temp_change_dic.items():
|
|
for node in self.context.clusterInfo.dbNodes:
|
|
self.change_node_info(node, value[1], key)
|
|
for inst in node.datanodes:
|
|
self.change_inst_info(inst, value[1], key)
|
|
|
|
def change_node_info(self, node, new_value, old_value):
|
|
if node.name == old_value:
|
|
node.name = new_value
|
|
for i in range(len(node.backIps)):
|
|
if node.backIps[i] == old_value:
|
|
node.backIps[i] = new_value
|
|
for i in range(len(node.virtualIp)):
|
|
if node.virtualIp[i] == old_value:
|
|
node.virtualIp[i] = new_value
|
|
for i in range(len(node.sshIps)):
|
|
if node.sshIps[i] == old_value:
|
|
node.sshIps[i] = new_value
|
|
self.logger.debug("Change the info of node %s successfully." % node.name)
|
|
|
|
def change_inst_info(self, inst, new_value, old_value):
|
|
if inst.hostname == old_value:
|
|
inst.hostname = new_value
|
|
if str(inst.port) == old_value:
|
|
inst.port = int(new_value)
|
|
if str(inst.haPort) == old_value:
|
|
inst.haPort = int(new_value)
|
|
for i in range(len(inst.listenIps)):
|
|
if inst.listenIps[i] == old_value:
|
|
inst.listenIps[i] = new_value
|
|
for i in range(len(inst.haIps)):
|
|
if inst.haIps[i] == old_value:
|
|
inst.haIps[i] = new_value
|
|
self.logger.debug("Change the DN inst on %s successfully." % inst.hostname)
|
|
|
|
def doRebuildConf(self):
|
|
"""
|
|
generating static configuration files for all nodes
|
|
input:NA
|
|
output:NA
|
|
"""
|
|
try:
|
|
self.logger.log(
|
|
"Generating static configuration files for all nodes.")
|
|
tmpDirName = ""
|
|
# Initialize the cluster information according to the XML file
|
|
self.context.clusterInfo = dbClusterInfo()
|
|
if self.context.g_opts.old_values:
|
|
self.context.clusterInfo.initFromStaticConfig(self.context.user)
|
|
self.change_cluster_info()
|
|
else:
|
|
self.context.clusterInfo.initFromXml(self.context.g_opts.confFile)
|
|
|
|
# 1.create a tmp dir
|
|
self.logger.log(
|
|
"Creating temp directory to store static configuration files.")
|
|
dirName = os.path.dirname(os.path.realpath(__file__))
|
|
tmpDirName = os.path.realpath(
|
|
"%s/../../static_config_files" % dirName)
|
|
cmd = "mkdir -p -m %s '%s'" % (
|
|
DefaultValue.KEY_DIRECTORY_MODE, tmpDirName)
|
|
(status, output) = subprocess.getstatusoutput(cmd)
|
|
if (status != 0):
|
|
raise Exception(
|
|
ErrorCode.GAUSS_502["GAUSS_50208"]
|
|
% "temporary directory" + "\nCommand:%s\nError: %s"
|
|
% (cmd, output))
|
|
self.logger.log("Successfully created the temp directory.")
|
|
|
|
# create static files
|
|
self.logger.log("Generating static configuration files.")
|
|
for dbNode in self.context.clusterInfo.dbNodes:
|
|
staticConfigPath = "%s/cluster_static_config_%s" % (
|
|
tmpDirName, dbNode.name)
|
|
self.context.clusterInfo.saveToStaticConfig(staticConfigPath,
|
|
dbNode.id)
|
|
self.logger.log(
|
|
"Successfully generated static configuration files.")
|
|
self.logger.log(
|
|
"Static configuration files for all nodes are saved in %s."
|
|
% tmpDirName)
|
|
|
|
# check if need send static config files
|
|
if not self.context.g_opts.distribute:
|
|
self.logger.debug(
|
|
"No need to distribute static configuration files "
|
|
"to installation directory.")
|
|
return
|
|
|
|
# distribute static config file
|
|
self.logger.log(
|
|
"Distributing static configuration files to all nodes.")
|
|
for dbNode in self.context.clusterInfo.dbNodes:
|
|
if (dbNode.name != NetUtil.GetHostIpOrName()):
|
|
cmd = \
|
|
"pscp -H %s '%s'/cluster_static_config_%s '%s'" \
|
|
"/bin/cluster_static_config" % (
|
|
dbNode.name, tmpDirName,
|
|
dbNode.name, self.context.clusterInfo.appPath)
|
|
else:
|
|
cmd = \
|
|
"cp '%s'/cluster_static_config_%s '%s'" \
|
|
"/bin/cluster_static_config" % (
|
|
tmpDirName,
|
|
dbNode.name, self.context.clusterInfo.appPath)
|
|
(status, output) = subprocess.getstatusoutput(cmd)
|
|
if (status != 0):
|
|
raise Exception(
|
|
ErrorCode.GAUSS_502["GAUSS_50216"]
|
|
% "static configuration file"
|
|
+ "Node: %s.\nCommand: \n%s\nError: \n%s"
|
|
% (dbNode.name, cmd, output))
|
|
self.logger.log(
|
|
"Successfully distributed static configuration files.")
|
|
|
|
except Exception as e:
|
|
FileUtil.removeDirectory(tmpDirName)
|
|
raise Exception(str(e))
|
|
|
|
##########################################################################
|
|
# doReplaceSSLCert start
|
|
##########################################################################
|
|
def doReplaceSSLCert(self):
|
|
"""
|
|
function: replace ssl cert files
|
|
input: NA
|
|
output: NA
|
|
"""
|
|
try:
|
|
# Initialize the cluster information according to the xml file
|
|
self.context.clusterInfo = dbClusterInfo()
|
|
self.context.clusterInfo.initFromStaticConfig(
|
|
UserUtil.getPathOwner(self.context.g_opts.certFile)[0])
|
|
self.sshTool = SshTool(
|
|
self.context.clusterInfo.getClusterNodeNames(),
|
|
self.logger.logFile)
|
|
except Exception as e:
|
|
raise Exception(str(e))
|
|
|
|
try:
|
|
self.logger.log("Starting ssl cert files replace.", "addStep")
|
|
tempDir = os.path.join(EnvUtil.getTmpDirFromEnv(),
|
|
"tempCertDir")
|
|
|
|
# unzip files to temp directory
|
|
if (os.path.exists(tempDir)):
|
|
FileUtil.removeDirectory(tempDir)
|
|
FileUtil.createDirectory(tempDir, True,
|
|
DefaultValue.KEY_DIRECTORY_MODE)
|
|
CompressUtil.decompressZipFiles(self.context.g_opts.certFile, tempDir)
|
|
|
|
realCertList = DefaultValue.CERT_FILES_LIST
|
|
clientCertList = DefaultValue.CLIENT_CERT_LIST
|
|
# check file exists
|
|
for clientCert in clientCertList:
|
|
sslFile = os.path.join(tempDir, clientCert)
|
|
if (not os.path.isfile(sslFile)):
|
|
raise Exception(
|
|
(ErrorCode.GAUSS_502["GAUSS_50201"] % sslFile) + \
|
|
"Missing SSL client cert file in ZIP file.")
|
|
|
|
certList = []
|
|
dnDict = self.getDnNodeDict()
|
|
for cert in realCertList:
|
|
sslFile = os.path.join(tempDir, cert)
|
|
|
|
if (not os.path.isfile(
|
|
sslFile) and cert != DefaultValue.SSL_CRL_FILE):
|
|
raise Exception(
|
|
(ErrorCode.GAUSS_502["GAUSS_50201"] % sslFile) + \
|
|
"Missing SSL server cert file in ZIP file.")
|
|
if (os.path.isfile(sslFile)):
|
|
certList.append(cert)
|
|
|
|
# distribute cert files to datanodes
|
|
self.doDNBackup()
|
|
self.distributeDNCert(certList, dnDict)
|
|
|
|
# clear temp directory
|
|
FileUtil.removeDirectory(tempDir)
|
|
if (not self.context.g_opts.localMode):
|
|
self.logger.log(
|
|
"Successfully distributed cert files on all nodes.")
|
|
except Exception as e:
|
|
FileUtil.removeDirectory(tempDir)
|
|
raise Exception(str(e))
|
|
|
|
def isDnEmpty(self, nodeName=""):
|
|
"""
|
|
function: Is there exists empty file in dbnodes directory.
|
|
input: node name
|
|
output: True/False
|
|
"""
|
|
allDnNodeDict = self.getDnNodeDict()
|
|
nodeDnDir = allDnNodeDict[nodeName]
|
|
emptyCert = os.path.join(nodeDnDir, EMPTY_CERT)
|
|
status = self.sshTool.checkRemoteFileExist(
|
|
nodeName, emptyCert,
|
|
self.context.g_opts.mpprcFile)
|
|
return status
|
|
|
|
def backup_cert_files(self, ssl_dir):
|
|
"""
|
|
function: Back up the certificate files in the ssl_dir directory.
|
|
input: certificate directory
|
|
output: NA
|
|
"""
|
|
if self.context.g_opts.localMode:
|
|
# empty flag
|
|
if os.path.isfile(
|
|
os.path.join(ssl_dir, DefaultValue.CERT_BACKUP_FILE)):
|
|
FileUtil.removeFile(
|
|
os.path.join(ssl_dir, DefaultValue.CERT_BACKUP_FILE))
|
|
if not os.path.exists(os.path.join(ssl_dir, EMPTY_FLAG)):
|
|
os.mknod(os.path.join(ssl_dir, EMPTY_FLAG))
|
|
cmd = " %s && " % CmdUtil.getCdCmd(ssl_dir)
|
|
cmd += CompressUtil.getCompressFilesCmd(DefaultValue.CERT_BACKUP_FILE, "*")
|
|
(status, output) = CmdUtil.retryGetstatusoutput(cmd)
|
|
if status != 0:
|
|
FileUtil.removeFile(os.path.join(ssl_dir, EMPTY_FLAG))
|
|
raise Exception(ErrorCode.GAUSS_514["GAUSS_51400"] % \
|
|
cmd + "Failed to backup cert files on local node." +
|
|
"Error: \n%s" % output)
|
|
if os.path.exists(os.path.join(ssl_dir, EMPTY_FLAG)):
|
|
os.remove(os.path.join(ssl_dir, EMPTY_FLAG))
|
|
else:
|
|
sshcmd = "if [ -d '%s' ]; then " % ssl_dir
|
|
sshcmd += " %s && " % CmdUtil.getCdCmd(ssl_dir)
|
|
sshcmd += g_file.SHELL_CMD_DICT["deleteFile"] % (
|
|
DefaultValue.CERT_BACKUP_FILE, DefaultValue.CERT_BACKUP_FILE) + ";"
|
|
sshcmd += CmdUtil.getTouchCmd(EMPTY_FLAG)
|
|
sshcmd += " && " + CompressUtil.getCompressFilesCmd(DefaultValue.CERT_BACKUP_FILE, "*;")
|
|
sshcmd += g_file.SHELL_CMD_DICT["deleteFile"] % (EMPTY_FLAG, EMPTY_FLAG)
|
|
sshcmd += " && " + g_file.SHELL_CMD_DICT["changeMode"] % (
|
|
DefaultValue.KEY_FILE_MODE, DefaultValue.CERT_BACKUP_FILE)
|
|
sshcmd += "; fi"
|
|
self.sshTool.executeCommand(sshcmd, DefaultValue.SUCCESS,
|
|
[node.name for node in self.context.clusterInfo.dbNodes],
|
|
self.context.g_opts.mpprcFile)
|
|
|
|
def doDNBackup(self):
|
|
"""
|
|
function: backup SSL cert files on single_inst cluster.
|
|
input: backupFlag is a flag of exist DB in node
|
|
output: NA
|
|
"""
|
|
self.logger.log("Backing up old ssl cert files.")
|
|
|
|
backupList = DefaultValue.CERT_FILES_LIST[:]
|
|
allDnNodeDict = self.getDnNodeDict()
|
|
normalNodeList = []
|
|
dss_ssl_dir = os.path.join(ClusterDir.getInstallDir(self.context.g_opts.user),
|
|
"share/sslcert/dss/")
|
|
cm_ssl_dir = os.path.join(ClusterDir.getInstallDir(self.context.g_opts.user),
|
|
"share/sslcert/cm/")
|
|
om_ssl_dir = os.path.join(ClusterDir.getInstallDir(self.context.g_opts.user),
|
|
"share/sslcert/om/")
|
|
|
|
tarBackupList = []
|
|
if (self.context.g_opts.localMode):
|
|
self.logger.debug("Backing up database node SSL cert files.")
|
|
nodeDnDir = allDnNodeDict[NetUtil.GetHostIpOrName()]
|
|
backupFlagFile = os.path.join(nodeDnDir, "certFlag")
|
|
if (os.path.isfile(backupFlagFile)):
|
|
self.logger.log("There is no need to backup ssl cert files.")
|
|
return
|
|
|
|
os.mknod(backupFlagFile, ConstantsBase.KEY_FILE_PERMISSION)
|
|
for certFile in backupList:
|
|
realCertFile = os.path.join(nodeDnDir, certFile)
|
|
if (os.path.isfile(realCertFile)):
|
|
tarBackupList.append(certFile)
|
|
|
|
if (len(tarBackupList) == 0):
|
|
os.mknod(os.path.join(nodeDnDir, EMPTY_CERT))
|
|
cmd = " %s && " % CmdUtil.getCdCmd(nodeDnDir)
|
|
cmd += CompressUtil.getCompressFilesCmd(
|
|
DefaultValue.CERT_BACKUP_FILE, EMPTY_CERT)
|
|
else:
|
|
cmd = " %s && " % CmdUtil.getCdCmd(nodeDnDir)
|
|
cmd += "tar -zcvf %s" % (DefaultValue.CERT_BACKUP_FILE)
|
|
for certFile in tarBackupList:
|
|
cmd += " %s" % certFile
|
|
(status, output) = CmdUtil.retryGetstatusoutput(cmd)
|
|
if (status != 0):
|
|
raise Exception(
|
|
ErrorCode.GAUSS_514["GAUSS_51400"]
|
|
% cmd + "Failed backup gds cert files on local node."
|
|
+ "Error: \n%s" % output)
|
|
|
|
# Clear empty file
|
|
if (os.path.isfile(os.path.join(nodeDnDir, EMPTY_CERT))):
|
|
os.remove(os.path.join(nodeDnDir, EMPTY_CERT))
|
|
if os.path.isdir(dss_ssl_dir):
|
|
self.backup_cert_files(dss_ssl_dir)
|
|
if os.path.isdir(cm_ssl_dir):
|
|
self.backup_cert_files(cm_ssl_dir)
|
|
if os.path.isdir(om_ssl_dir):
|
|
self.backup_cert_files(om_ssl_dir)
|
|
self.logger.log("Successfully executed local backup.")
|
|
return
|
|
# 1 check backup flag file on all dbnodes.
|
|
for node in allDnNodeDict.keys():
|
|
nodeDnDir = allDnNodeDict[node]
|
|
backupFlagFile = os.path.join(nodeDnDir, "certFlag")
|
|
status = self.sshTool.checkRemoteFileExist(
|
|
node, backupFlagFile,
|
|
self.context.g_opts.mpprcFile)
|
|
if not status:
|
|
normalNodeList.append(node)
|
|
# 2 if exists flag file on anyone node, there will be return.
|
|
if (len(normalNodeList) != len(allDnNodeDict.keys())):
|
|
self.logger.log("There is no need to backup on all dbnodes.")
|
|
return
|
|
# 3 backup cert files on all dbnodes.
|
|
for node in allDnNodeDict.keys():
|
|
nodeDnDir = allDnNodeDict[node]
|
|
backupFlagFile = os.path.join(nodeDnDir, "certFlag")
|
|
backupTar = os.path.join(nodeDnDir, DefaultValue.CERT_BACKUP_FILE)
|
|
sshcmd = g_file.SHELL_CMD_DICT["overWriteFile"] % (
|
|
"backupflagfile", backupFlagFile)
|
|
sshcmd += " && " + g_file.SHELL_CMD_DICT["changeMode"] % (
|
|
DefaultValue.KEY_FILE_MODE, backupFlagFile)
|
|
self.sshTool.executeCommand(sshcmd,
|
|
DefaultValue.SUCCESS, [node],
|
|
self.context.g_opts.mpprcFile)
|
|
for certFile in backupList:
|
|
realCertFile = os.path.join(nodeDnDir, certFile)
|
|
status = self.sshTool.checkRemoteFileExist(
|
|
node, realCertFile,
|
|
self.context.g_opts.mpprcFile)
|
|
if status:
|
|
tarBackupList.append(certFile)
|
|
# if no cert files,
|
|
# there will be create a file for '.tar' file.
|
|
if (len(tarBackupList) == 0):
|
|
sshcmd = CmdUtil.getCreateFileCmd(
|
|
os.path.join(nodeDnDir, EMPTY_CERT))
|
|
self.sshTool.executeCommand(sshcmd,
|
|
DefaultValue.SUCCESS, [node],
|
|
self.context.g_opts.mpprcFile)
|
|
sshcmd = " %s && " % CmdUtil.getCdCmd(nodeDnDir)
|
|
sshcmd += CompressUtil.getCompressFilesCmd(
|
|
DefaultValue.CERT_BACKUP_FILE, EMPTY_CERT)
|
|
else:
|
|
sshcmd = " %s && " % CmdUtil.getCdCmd(nodeDnDir)
|
|
sshcmd += "tar -zcvf %s" % (DefaultValue.CERT_BACKUP_FILE)
|
|
for certDir in tarBackupList:
|
|
sshcmd += " %s" % certDir
|
|
self.sshTool.executeCommand(sshcmd,
|
|
DefaultValue.SUCCESS, [node],
|
|
self.context.g_opts.mpprcFile)
|
|
# Clear empty file
|
|
if (self.isDnEmpty(node)):
|
|
sshcmd = g_file.SHELL_CMD_DICT["deleteFile"] % (
|
|
os.path.join(nodeDnDir, EMPTY_CERT),
|
|
os.path.join(nodeDnDir, EMPTY_CERT))
|
|
self.sshTool.executeCommand(sshcmd,
|
|
DefaultValue.SUCCESS, [node],
|
|
self.context.g_opts.mpprcFile)
|
|
self.logger.log(
|
|
"Successfully backup SSL cert files on [%s]." % node)
|
|
sshcmd = g_file.SHELL_CMD_DICT["changeMode"] % (
|
|
DefaultValue.KEY_FILE_MODE, backupTar)
|
|
self.sshTool.executeCommand(sshcmd,
|
|
DefaultValue.SUCCESS, [node],
|
|
self.context.g_opts.mpprcFile)
|
|
self.backup_cert_files(dss_ssl_dir)
|
|
self.backup_cert_files(cm_ssl_dir)
|
|
self.backup_cert_files(om_ssl_dir)
|
|
|
|
def local_rollback_cert(self, ssl_dir, cert_list):
|
|
"""
|
|
function: rollback SSL cert files
|
|
input: Certificate directory, which is used to replace the certificate file.
|
|
output: NA
|
|
"""
|
|
# create dss temp dir
|
|
temp_dir = os.path.join(ssl_dir, "dssTempDir")
|
|
if not os.path.exists(temp_dir):
|
|
os.mkdir(temp_dir)
|
|
else:
|
|
FileUtil.removeDirectory(temp_dir)
|
|
os.mkdir(temp_dir)
|
|
|
|
# backup cert cert to temp dir
|
|
for num in iter(cert_list):
|
|
certfile = os.path.join(ssl_dir, num)
|
|
if os.path.exists(certfile):
|
|
FileUtil.moveFile(certfile, temp_dir)
|
|
|
|
# decompress backup package to cert dir
|
|
cmd = "cd '%s' && if [ -f '%s' ];then tar -zxf %s;fi" % \
|
|
(ssl_dir, DefaultValue.CERT_BACKUP_FILE, DefaultValue.CERT_BACKUP_FILE)
|
|
status, _ = subprocess.getstatusoutput(cmd)
|
|
if status != 0:
|
|
# copy cert files from temp dir to cert dir
|
|
cmd = "cp '%s'/* '%s' && rm -rf '%s' && rm -rf '%s'" % \
|
|
(temp_dir, temp_dir, temp_dir, os.path.join(temp_dir, EMPTY_FLAG))
|
|
CmdUtil.getstatusoutput_by_fast_popen(cmd)
|
|
|
|
FileUtil.removeDirectory(temp_dir)
|
|
FileUtil.removeDirectory(os.path.join(temp_dir, EMPTY_FLAG))
|
|
self.logger.debug("Successfully rollback ssl cert files.")
|
|
|
|
def cert_rollback(self):
|
|
"""
|
|
function: Certificate Rollback
|
|
input: NA
|
|
output: NA
|
|
"""
|
|
dss_ssl_dir = os.path.join(ClusterDir.getInstallDir(
|
|
self.context.g_opts.user), "share/sslcert/dss/")
|
|
cm_ssl_dir = os.path.join(ClusterDir.getInstallDir(
|
|
self.context.g_opts.user), "share/sslcert/cm/")
|
|
om_ssl_dir = os.path.join(ClusterDir.getInstallDir(
|
|
self.context.g_opts.user), "share/sslcert/om/")
|
|
if self.context.g_opts.localMode:
|
|
if os.path.exists(dss_ssl_dir) and EnvUtil.get_dss_ssl_status(
|
|
getpass.getuser()) == 'on':
|
|
self.local_rollback_cert(dss_ssl_dir,
|
|
DefaultValue.GDS_CERT_LIST)
|
|
self.regen_dss_cert()
|
|
self.logger.log("Successfully rollback dss ssl cert files.")
|
|
if os.path.exists(cm_ssl_dir):
|
|
self.local_rollback_cert(cm_ssl_dir, DefaultValue.GDS_CERT_LIST)
|
|
self.logger.log("Successfully rollback cm ssl cert files.")
|
|
if os.path.exists(om_ssl_dir):
|
|
self.local_rollback_cert(om_ssl_dir, DefaultValue.SERVER_CERT_LIST)
|
|
self.logger.log("Successfully rollback om ssl cert files.")
|
|
else:
|
|
# rollback dss cert files
|
|
if os.path.exists(dss_ssl_dir) and EnvUtil.get_dss_ssl_status(
|
|
getpass.getuser()) == 'on':
|
|
self.rollback_cert(dss_ssl_dir, DefaultValue.GDS_CERT_LIST)
|
|
self.regen_dss_cert()
|
|
self.logger.log("Successfully replace dss SSL cert files.")
|
|
|
|
# rollback cm cert files
|
|
if os.path.exists(cm_ssl_dir):
|
|
self.rollback_cert(cm_ssl_dir, DefaultValue.GDS_CERT_LIST)
|
|
self.logger.log("Successfully replace cm SSL cert files.")
|
|
|
|
# rollback om cert files
|
|
if os.path.exists(om_ssl_dir):
|
|
self.rollback_cert(om_ssl_dir, DefaultValue.SERVER_CERT_LIST)
|
|
self.logger.log("Successfully replace om SSL cert files.")
|
|
|
|
def doDNSSLCertRollback(self):
|
|
"""
|
|
function: rollback SSL cert file in DN instance directory
|
|
input: NA
|
|
output: NA
|
|
"""
|
|
self.context.clusterInfo = dbClusterInfo()
|
|
self.context.clusterInfo.initFromStaticConfig(
|
|
pwd.getpwuid(os.getuid()).pw_name)
|
|
self.sshTool = SshTool(self.context.clusterInfo.getClusterNodeNames(),
|
|
self.logger.logFile)
|
|
backupList = DefaultValue.CERT_FILES_LIST[:]
|
|
|
|
allDnNodeDict = self.getDnNodeDict()
|
|
noBackupList = []
|
|
|
|
temp = "tempDir"
|
|
if self.context.g_opts.localMode:
|
|
if ((NetUtil.GetHostIpOrName() in allDnNodeDict.keys()) and
|
|
os.path.isfile(os.path.join(
|
|
allDnNodeDict[NetUtil.GetHostIpOrName()],
|
|
DefaultValue.CERT_BACKUP_FILE))):
|
|
|
|
localDnDir = allDnNodeDict[NetUtil.GetHostIpOrName()]
|
|
tempDir = os.path.join(localDnDir, temp)
|
|
if (os.path.exists(tempDir)):
|
|
FileUtil.removeDirectory(tempDir)
|
|
os.mkdir(tempDir, ConstantsBase.KEY_DIRECTORY_PERMISSION)
|
|
|
|
for certFile in backupList:
|
|
realCertFile = os.path.join(localDnDir, certFile)
|
|
if (os.path.exists(realCertFile)):
|
|
FileUtil.moveFile(realCertFile, tempDir)
|
|
|
|
cmd = "cd '%s' && if [ -f '%s' ];then tar -zxvf %s;fi" % \
|
|
(localDnDir, DefaultValue.CERT_BACKUP_FILE,
|
|
DefaultValue.CERT_BACKUP_FILE)
|
|
(status, output) = subprocess.getstatusoutput(cmd)
|
|
if (status != 0):
|
|
cmd = "cp '%s'/* '%s' && rm -rf '%s'" % (
|
|
tempDir, localDnDir, tempDir)
|
|
(status, output) = subprocess.getstatusoutput(cmd)
|
|
raise Exception(
|
|
(ErrorCode.GAUSS_514["GAUSS_51400"] % cmd)
|
|
+ "Failed uncompression SSL backup file."
|
|
+ "Error: \n%s" % output)
|
|
|
|
# remove temp directory
|
|
if (os.path.exists(tempDir)):
|
|
FileUtil.removeDirectory(tempDir)
|
|
|
|
# set guc option
|
|
if (os.path.isfile(
|
|
os.path.join(localDnDir, DefaultValue.SSL_CRL_FILE))):
|
|
cmd = \
|
|
"gs_guc set -D %s " \
|
|
"-c \"ssl_crl_file=\'%s\'\"" \
|
|
% (localDnDir, DefaultValue.SSL_CRL_FILE)
|
|
else:
|
|
cmd = \
|
|
"gs_guc set -D %s " \
|
|
"-c \"ssl_crl_file=\'\'\"" % localDnDir
|
|
(status, output) = subprocess.getstatusoutput(cmd)
|
|
if (status != 0):
|
|
raise Exception(
|
|
ErrorCode.GAUSS_514["GAUSS_51400"]
|
|
% cmd + "Error: \n%s" % output)
|
|
|
|
if (os.path.isfile(os.path.join(localDnDir, EMPTY_CERT))):
|
|
os.remove(os.path.join(localDnDir, EMPTY_CERT))
|
|
self.cert_rollback()
|
|
|
|
self.logger.log(
|
|
"Successfully rollback SSL cert files with local mode.")
|
|
return
|
|
else:
|
|
self.cert_rollback()
|
|
self.logger.log("There is not node data exists backup files.")
|
|
return
|
|
# 1.check backup file "gsql_cert_backup.tar.gz" on all dbnodes.
|
|
for node in allDnNodeDict.keys():
|
|
backupGzFile = os.path.join(allDnNodeDict[node],
|
|
DefaultValue.CERT_BACKUP_FILE)
|
|
status = self.sshTool.checkRemoteFileExist(
|
|
node, backupGzFile,
|
|
self.context.g_opts.mpprcFile)
|
|
if not status:
|
|
noBackupList.append(node)
|
|
if (len(noBackupList) > 0):
|
|
raise Exception(
|
|
(ErrorCode.GAUSS_502["GAUSS_50201"]
|
|
% DefaultValue.CERT_BACKUP_FILE)
|
|
+ "Can't rollback SSL cert files on %s." % noBackupList)
|
|
|
|
# 2.perform rollback on all dbnodes.
|
|
for node in allDnNodeDict.keys():
|
|
backupGzFile = os.path.join(
|
|
allDnNodeDict[node], DefaultValue.CERT_BACKUP_FILE)
|
|
# 2-1.move SSL cert files in dn directory to temp directory.
|
|
sshcmd = "cd '%s' && if [ -d '%s' ];then rm -rf '%s'" \
|
|
" && mkdir '%s';else mkdir '%s';fi" % \
|
|
(allDnNodeDict[node], temp, temp, temp, temp)
|
|
self.sshTool.executeCommand(sshcmd,
|
|
DefaultValue.SUCCESS,
|
|
[node], self.context.g_opts.mpprcFile)
|
|
for certFile in backupList:
|
|
realCertFile = os.path.join(allDnNodeDict[node], certFile)
|
|
sshcmd = " %s && " % CmdUtil.getCdCmd(
|
|
os.path.join(allDnNodeDict[node], temp))
|
|
sshcmd += g_file.SHELL_CMD_DICT["renameFile"] % (
|
|
realCertFile, realCertFile, "./")
|
|
self.sshTool.executeCommand(
|
|
sshcmd,
|
|
DefaultValue.SUCCESS,
|
|
[node],
|
|
self.context.g_opts.mpprcFile)
|
|
|
|
# 2-2.uncompression "gsql_cert_backup.tar.gz" file
|
|
sshcmd = "cd '%s' && if [ -f '%s' ];then tar -zxvf %s;fi" % \
|
|
(allDnNodeDict[node], DefaultValue.CERT_BACKUP_FILE,
|
|
DefaultValue.CERT_BACKUP_FILE)
|
|
self.sshTool.executeCommand(sshcmd,
|
|
DefaultValue.SUCCESS,
|
|
[node],
|
|
self.context.g_opts.mpprcFile)
|
|
|
|
# 2-3.clear temp directory
|
|
sshcmd = " %s && " % CmdUtil.getCdCmd(allDnNodeDict[node])
|
|
sshcmd += g_file.SHELL_CMD_DICT["deleteDir"] % (temp, temp)
|
|
self.sshTool.executeCommand(sshcmd,
|
|
DefaultValue.SUCCESS,
|
|
[node],
|
|
self.context.g_opts.mpprcFile)
|
|
|
|
# 2-4.is have "sslcrl-file.crl",config 'ssl_crl_file' option
|
|
status = self.sshTool.checkRemoteFileExist(
|
|
node, os.path.join(
|
|
allDnNodeDict[node],
|
|
DefaultValue.SSL_CRL_FILE),
|
|
self.context.g_opts.mpprcFile)
|
|
# exists 'sslcrl-file.crl' file ,config option of 'postgresql.conf'
|
|
if (status):
|
|
if node == NetUtil.GetHostIpOrName():
|
|
sshcmd = \
|
|
"gs_guc set -D %s " \
|
|
"-c \"ssl_crl_file='%s'\"" \
|
|
% (allDnNodeDict[node], DefaultValue.SSL_CRL_FILE)
|
|
else:
|
|
sshcmd = "gs_guc set -D %s " \
|
|
"-c \"ssl_crl_file=\\\\\\'%s\\\\\\'\"" \
|
|
% (allDnNodeDict[node], DefaultValue.SSL_CRL_FILE)
|
|
self.sshTool.executeCommand(sshcmd,
|
|
DefaultValue.SUCCESS,
|
|
[node],
|
|
self.context.g_opts.mpprcFile)
|
|
else:
|
|
if (node == NetUtil.GetHostIpOrName()):
|
|
sshcmd = "gs_guc set " \
|
|
"-D %s -c \"ssl_crl_file=''\"" % (
|
|
allDnNodeDict[node])
|
|
else:
|
|
sshcmd = "gs_guc set " \
|
|
"-D %s -c \"ssl_crl_file=\\\\\\'\\\\\\'\"" \
|
|
% (allDnNodeDict[node])
|
|
self.sshTool.executeCommand(sshcmd,
|
|
DefaultValue.SUCCESS,
|
|
[node],
|
|
self.context.g_opts.mpprcFile)
|
|
|
|
# Clear empty file.
|
|
if (self.isDnEmpty(node)):
|
|
sshcmd = g_file.SHELL_CMD_DICT["deleteFile"] % (
|
|
os.path.join(allDnNodeDict[node], EMPTY_CERT),
|
|
os.path.join(allDnNodeDict[node], EMPTY_CERT))
|
|
self.sshTool.executeCommand(sshcmd,
|
|
DefaultValue.SUCCESS,
|
|
[node],
|
|
self.context.g_opts.mpprcFile)
|
|
self.logger.log(
|
|
"Successfully rollback SSL cert files on [%s]." % node)
|
|
|
|
self.cert_rollback()
|
|
|
|
def rollback_cert(self, ssl_dir, cert_list):
|
|
"""
|
|
function: Delete the certificate and decompress the backup package.
|
|
input: Certificate directory, certificate list
|
|
output: NA
|
|
"""
|
|
cmd = "cd '%s';rm -f" % ssl_dir
|
|
for num in cert_list:
|
|
cmd += " {}".format(num)
|
|
sshcmd = "%s && tar -zxf %s;rm -f '%s'" % (cmd, DefaultValue.CERT_BACKUP_FILE, EMPTY_FLAG)
|
|
self.sshTool.executeCommand(sshcmd,
|
|
DefaultValue.SUCCESS,
|
|
[node.name for node in self.context.clusterInfo.dbNodes],
|
|
self.context.g_opts.mpprcFile)
|
|
|
|
def getDnNodeDict(self):
|
|
"""
|
|
function: get dbnodes information
|
|
input: NA
|
|
output: dictionary
|
|
"""
|
|
clusterDnNodes = {}
|
|
if (not self.context.clusterInfo.isSingleInstCluster()):
|
|
return clusterDnNodes
|
|
for node in self.context.clusterInfo.dbNodes:
|
|
if (len(node.datanodes) > 0):
|
|
clusterDnNodes[node.datanodes[0].hostname] = node.datanodes[
|
|
0].datadir
|
|
self.logger.debug("Successfully get database node dict.")
|
|
return clusterDnNodes
|
|
|
|
def distribute_ssl_cert(self, params):
|
|
"""
|
|
function: Distributing SSL Certificate Files
|
|
input: Certificate parameters
|
|
output: NA
|
|
"""
|
|
cert_path_list, ssl_dir, cert_lit, mode = params
|
|
if self.context.g_opts.localMode:
|
|
cert_path_list_num = len(cert_path_list)
|
|
for num in range(cert_path_list_num):
|
|
# distribute cert
|
|
if os.path.isfile(os.path.join(ssl_dir, cert_lit[num])):
|
|
os.remove(os.path.join(ssl_dir, cert_lit[num]))
|
|
if os.path.isfile(cert_path_list[num]):
|
|
FileUtil.cpFile(cert_path_list[num],
|
|
os.path.join(ssl_dir, cert_lit[num]))
|
|
FileUtil.changeMode(mode,
|
|
os.path.join(ssl_dir, cert_lit[num]))
|
|
else:
|
|
cert_lit_num = len(cert_lit)
|
|
for num in range(cert_lit_num):
|
|
sshcmd = g_file.SHELL_CMD_DICT["deleteFile"] % (
|
|
os.path.join(ssl_dir, cert_lit[num]),
|
|
os.path.join(ssl_dir, cert_lit[num]))
|
|
self.sshTool.executeCommand(
|
|
sshcmd,
|
|
DefaultValue.SUCCESS,
|
|
[node.name for node in self.context.clusterInfo.dbNodes],
|
|
self.context.g_opts.mpprcFile)
|
|
cert_path_list_num = len(cert_path_list)
|
|
for num in range(cert_path_list_num):
|
|
if os.path.exists(cert_path_list[num]):
|
|
cmd = g_file.SHELL_CMD_DICT["changeMode"] % (
|
|
mode, cert_path_list[num])
|
|
(status, output) = subprocess.getstatusoutput(cmd)
|
|
if status != 0:
|
|
raise Exception("Failed to chmod dss cert files" + "Error: \n%s" % output)
|
|
self.sshTool.scpFiles(cert_path_list[num], ssl_dir,
|
|
[node.name for node in self.context.clusterInfo.dbNodes])
|
|
|
|
def regen_dss_cert(self):
|
|
"""
|
|
function: Re-generate the ciphertext of the DSS.
|
|
input: NA
|
|
output: NA
|
|
"""
|
|
try:
|
|
self.logger.debug("Re-generate the ciphertext of the DSS")
|
|
cmd = "source %s; %s -t dss_cert_replacer -U %s -l %s" % (
|
|
self.context.g_opts.mpprcFile,
|
|
OMCommand.getLocalScript("Local_Collect"), self.context.user,
|
|
self.context.localLog)
|
|
CmdExecutor.execCommandWithMode(
|
|
cmd, self.sshTool, self.context.g_opts.localMode,
|
|
self.context.g_opts.mpprcFile,
|
|
[node.name for node in self.context.clusterInfo.dbNodes])
|
|
self.logger.debug("The cmd is %s " % cmd)
|
|
except Exception as e:
|
|
self.logger.log("Failed to re-generate the ciphertext of the DSS.")
|
|
raise Exception(str(e))
|
|
|
|
def distribute_cert(self):
|
|
"""
|
|
function: Distributing Certificates
|
|
input: NA
|
|
output: NA
|
|
"""
|
|
tempDir = "tempCertDir"
|
|
gphost = EnvUtil.getTmpDirFromEnv()
|
|
cm_dss_sslcert_cert_path_list = []
|
|
server_sslcert_cert_path_list = []
|
|
dss_ssl_dir = os.path.join(ClusterDir.getInstallDir(
|
|
self.context.g_opts.user),
|
|
"share/sslcert/dss/")
|
|
cm_ssl_dir = os.path.join(ClusterDir.getInstallDir(
|
|
self.context.g_opts.user),
|
|
"share/sslcert/cm/")
|
|
om_ssl_dir = os.path.join(ClusterDir.getInstallDir(
|
|
self.context.g_opts.user),
|
|
"share/sslcert/om/")
|
|
for num in range(len(DefaultValue.GDS_CERT_LIST)):
|
|
sslPath = os.path.join(os.path.join(gphost, tempDir),
|
|
DefaultValue.GDS_CERT_LIST[num])
|
|
cm_dss_sslcert_cert_path_list.append(sslPath)
|
|
for num in range(len(DefaultValue.SERVER_CERT_LIST)):
|
|
sslPath = os.path.join(os.path.join(gphost, tempDir),
|
|
DefaultValue.SERVER_CERT_LIST[num])
|
|
server_sslcert_cert_path_list.append(sslPath)
|
|
|
|
# distribute dss SSL cert
|
|
if os.path.isdir(dss_ssl_dir) and EnvUtil.get_dss_ssl_status(
|
|
getpass.getuser()) == 'on':
|
|
self.distribute_ssl_cert((cm_dss_sslcert_cert_path_list,
|
|
dss_ssl_dir,
|
|
DefaultValue.GDS_CERT_LIST,
|
|
DefaultValue.MIN_FILE_MODE))
|
|
self.regen_dss_cert()
|
|
self.logger.log("Successfully replace dss ssl cert files.")
|
|
|
|
# distribute cm SSL cert
|
|
if os.path.isdir(cm_ssl_dir):
|
|
self.distribute_ssl_cert((cm_dss_sslcert_cert_path_list,
|
|
cm_ssl_dir,
|
|
DefaultValue.GDS_CERT_LIST,
|
|
DefaultValue.MIN_FILE_MODE))
|
|
self.logger.log("Successfully replace cm ssl cert files.")
|
|
|
|
# distribute om SSL cert
|
|
if os.path.isdir(om_ssl_dir):
|
|
self.distribute_ssl_cert((server_sslcert_cert_path_list,
|
|
om_ssl_dir,
|
|
DefaultValue.SERVER_CERT_LIST,
|
|
DefaultValue.KEY_FILE_MODE))
|
|
self.logger.log("Successfully replace om ssl cert files.")
|
|
|
|
def distributeDNCert(self, certList, dnDict=None):
|
|
"""
|
|
function: distribute ssl cert files on single_inst cluster
|
|
input: certList: cert files list
|
|
dnDict: dictionary
|
|
output: NA
|
|
"""
|
|
tempDir = "tempCertDir"
|
|
gphost = EnvUtil.getTmpDirFromEnv()
|
|
if dnDict is None:
|
|
dnDict = {}
|
|
dnName = dnDict.keys()
|
|
certPathList = []
|
|
self.logger.debug(certList)
|
|
|
|
for num in iter(certList):
|
|
sslPath = os.path.join(os.path.join(gphost, tempDir), num)
|
|
certPathList.append(sslPath)
|
|
# local mode
|
|
if self.context.g_opts.localMode:
|
|
localDnDir = dnDict[NetUtil.GetHostIpOrName()]
|
|
for num in range(len(certList)):
|
|
# distribute gsql SSL cert
|
|
if os.path.isfile(os.path.join(localDnDir, certList[num])):
|
|
os.remove(os.path.join(localDnDir, certList[num]))
|
|
if os.path.isfile(certPathList[num]):
|
|
FileUtil.cpFile(certPathList[num],
|
|
os.path.join(localDnDir, certList[num]))
|
|
FileUtil.changeMode(DefaultValue.KEY_FILE_MODE,
|
|
os.path.join(localDnDir, certList[num]))
|
|
|
|
self.distribute_cert()
|
|
# remove 'sslcrl-file.crl' file
|
|
if (DefaultValue.SSL_CRL_FILE not in certList and
|
|
os.path.isfile(
|
|
os.path.join(localDnDir, DefaultValue.SSL_CRL_FILE))):
|
|
os.remove(os.path.join(localDnDir, DefaultValue.SSL_CRL_FILE))
|
|
|
|
# config 'sslcrl-file.crl' option in 'postgresql.conf'
|
|
if (os.path.isfile(
|
|
os.path.join(localDnDir, DefaultValue.SSL_CRL_FILE))):
|
|
cmd = "gs_guc set " \
|
|
"-D %s -c \"ssl_crl_file=\'%s\'\"" % \
|
|
(localDnDir, DefaultValue.SSL_CRL_FILE)
|
|
(status, output) = subprocess.getstatusoutput(cmd)
|
|
if (status != 0):
|
|
raise Exception(
|
|
(ErrorCode.GAUSS_514["GAUSS_51400"] % cmd)
|
|
+ "Failed set 'ssl_crl_file' option."
|
|
+ "Error: \n%s" % output)
|
|
else:
|
|
cmd = "gs_guc set -D %s -c \"ssl_crl_file=\'\'\"" \
|
|
% localDnDir
|
|
(status, output) = subprocess.getstatusoutput(cmd)
|
|
if (status != 0):
|
|
raise Exception(
|
|
(ErrorCode.GAUSS_514["GAUSS_51400"] % cmd)
|
|
+ "Failed set 'ssl_crl_file' option."
|
|
+ "Error: \n%s" % output)
|
|
# remove backup flag file 'certFlag'
|
|
if (os.path.isfile(os.path.join(localDnDir, 'certFlag'))):
|
|
os.remove(os.path.join(localDnDir, 'certFlag'))
|
|
self.logger.log(
|
|
"Replace SSL cert files with local mode successfully.")
|
|
return
|
|
# not local mode
|
|
for node in dnName:
|
|
for num in range(len(certList)):
|
|
sshcmd = g_file.SHELL_CMD_DICT["deleteFile"] % (
|
|
os.path.join(dnDict[node], certList[num]),
|
|
os.path.join(dnDict[node], certList[num]))
|
|
self.sshTool.executeCommand(sshcmd,
|
|
DefaultValue.SUCCESS,
|
|
[node],
|
|
self.context.g_opts.mpprcFile)
|
|
|
|
if (os.path.exists(certPathList[num])):
|
|
self.sshTool.scpFiles(certPathList[num], dnDict[node],
|
|
[node])
|
|
|
|
# change permission of cert file 600,
|
|
# there no need to is exists file,
|
|
# because the files must be exist.
|
|
sshcmd = g_file.SHELL_CMD_DICT["changeMode"] % (
|
|
DefaultValue.KEY_FILE_MODE,
|
|
os.path.join(dnDict[node], certList[num]))
|
|
self.sshTool.executeCommand(sshcmd,
|
|
DefaultValue.SUCCESS,
|
|
[node],
|
|
self.context.g_opts.mpprcFile)
|
|
|
|
if (DefaultValue.SSL_CRL_FILE in certList):
|
|
if (node == NetUtil.GetHostIpOrName()):
|
|
sshcmd = "gs_guc set " \
|
|
"-D %s -c \"ssl_crl_file='%s'\"" \
|
|
% (dnDict[node], DefaultValue.SSL_CRL_FILE)
|
|
else:
|
|
sshcmd = "gs_guc set " \
|
|
" -D %s -c \"ssl_crl_file=\\\\\\'%s\\\\\\'\"" \
|
|
% (dnDict[node], DefaultValue.SSL_CRL_FILE)
|
|
self.sshTool.executeCommand(sshcmd,
|
|
DefaultValue.SUCCESS,
|
|
[node],
|
|
self.context.g_opts.mpprcFile)
|
|
else:
|
|
# no ssl cert file there will delete old cert file,
|
|
# and config option ssl_crl_file = ''
|
|
sshcmd = g_file.SHELL_CMD_DICT["deleteFile"] % (
|
|
os.path.join(dnDict[node], DefaultValue.SSL_CRL_FILE),
|
|
os.path.join(dnDict[node], DefaultValue.SSL_CRL_FILE))
|
|
self.sshTool.executeCommand(sshcmd,
|
|
DefaultValue.SUCCESS,
|
|
[node],
|
|
self.context.g_opts.mpprcFile)
|
|
if (node == NetUtil.GetHostIpOrName()):
|
|
sshcmd = "gs_guc set " \
|
|
"-D %s -c \"ssl_crl_file=\'\'\"" % (dnDict[node])
|
|
else:
|
|
sshcmd = \
|
|
"gs_guc set " \
|
|
"-D %s " \
|
|
"-c \"ssl_crl_file=\\\\\\'\\\\\\'\"" % (dnDict[node])
|
|
self.sshTool.executeCommand(sshcmd,
|
|
DefaultValue.SUCCESS,
|
|
[node],
|
|
self.context.g_opts.mpprcFile)
|
|
# remove file 'sslcrl-file.crl'
|
|
sshcmd = g_file.SHELL_CMD_DICT["deleteFile"] % (
|
|
os.path.join(dnDict[node], DefaultValue.SSL_CRL_FILE),
|
|
os.path.join(dnDict[node], DefaultValue.SSL_CRL_FILE))
|
|
self.sshTool.executeCommand(sshcmd,
|
|
DefaultValue.SUCCESS,
|
|
[node],
|
|
self.context.g_opts.mpprcFile)
|
|
# remove backup flag file 'certFlag'
|
|
sshcmd = g_file.SHELL_CMD_DICT["deleteFile"] % (
|
|
os.path.join(dnDict[node], "certFlag"),
|
|
os.path.join(dnDict[node], "certFlag"))
|
|
self.sshTool.executeCommand(sshcmd,
|
|
DefaultValue.SUCCESS,
|
|
[node],
|
|
self.context.g_opts.mpprcFile)
|
|
self.logger.log("%s replace SSL cert files successfully." % node)
|
|
|
|
self.distribute_cert()
|
|
|
|
###########################################################################
|
|
# Kerberos Flow
|
|
###########################################################################
|
|
def doKerberos(self):
|
|
"""
|
|
function: operation kerberos
|
|
input: NA
|
|
output: NA
|
|
"""
|
|
try:
|
|
if self.context.g_opts.kerberosMode == "install":
|
|
self.logger.log("Starting install Kerberos.", "addStep")
|
|
cmd = "%s -m %s -U %s --%s" % \
|
|
(OMCommand.getLocalScript("Local_Kerberos"),
|
|
"install",
|
|
self.context.g_opts.clusterUser,
|
|
self.context.g_opts.kerberosType)
|
|
# local mode
|
|
(status, output) = subprocess.getstatusoutput(cmd)
|
|
if (status != 0):
|
|
raise Exception(ErrorCode.GAUSS_514["GAUSS_51400"] %
|
|
"Command: %s. Error:\n%s" % (cmd, output))
|
|
self.logger.log("Successfully install Kerberos.")
|
|
elif self.context.g_opts.kerberosMode == "uninstall":
|
|
self.logger.log("Starting uninstall Kerberos.", "addStep")
|
|
cmd = "%s -m %s -U %s" % \
|
|
(OMCommand.getLocalScript("Local_Kerberos"),
|
|
"uninstall",
|
|
self.context.g_opts.clusterUser)
|
|
# local mode
|
|
(status, output) = subprocess.getstatusoutput(cmd)
|
|
if status != 0:
|
|
raise Exception(ErrorCode.GAUSS_514["GAUSS_51400"] %
|
|
"Command: %s. Error:\n%s" % (cmd, output))
|
|
self.logger.log("Successfully uninstall Kerberos.")
|
|
except Exception as e:
|
|
raise Exception(str(e))
|
|
|
|
def checkRemoteFileExist(self, filepath):
|
|
"""
|
|
funciton:check file exist on remote node
|
|
input:filepath
|
|
output:dictionary
|
|
"""
|
|
existNodes = []
|
|
for nodeName in self.context.clusterInfo.getClusterNodeNames():
|
|
if (nodeName == NetUtil.GetHostIpOrName()):
|
|
continue
|
|
if (self.sshTool.checkRemoteFileExist(nodeName, filepath, "")):
|
|
existNodes.append(nodeName)
|
|
|
|
return existNodes
|
|
|
|
def recursivePath(self, filepath):
|
|
"""
|
|
function: recursive path
|
|
input: filepath
|
|
output: NA
|
|
"""
|
|
fileList = os.listdir(filepath)
|
|
for fileName in fileList:
|
|
fileName = os.path.join(filepath, fileName)
|
|
# change the owner of files
|
|
FileUtil.changeOwner(self.context.g_opts.user, fileName)
|
|
if (os.path.isfile(fileName)):
|
|
# change fileName permission
|
|
FileUtil.changeMode(DefaultValue.KEY_FILE_MODE, fileName)
|
|
else:
|
|
# change directory permission
|
|
FileUtil.changeMode(DefaultValue.KEY_DIRECTORY_MODE, fileName,
|
|
True)
|
|
self.recursivePath(fileName)
|
|
|
|
def stopCluster(self):
|
|
"""
|
|
function:Stop cluster
|
|
input:NA
|
|
output:NA
|
|
"""
|
|
pass
|
|
|
|
def startCluster(self):
|
|
"""
|
|
function:Start cluster
|
|
input:NA
|
|
output:NA
|
|
"""
|
|
pass
|