1326 lines
57 KiB
Python
1326 lines
57 KiB
Python
#!/usr/bin/env python3
|
|
# -*- coding:utf-8 -*-
|
|
#############################################################################
|
|
# Portions Copyright (c) 2020 Huawei Technologies Co.,Ltd.
|
|
# Portions Copyright (c) 2007 Agendaless Consulting and Contributors.
|
|
#
|
|
# 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 : KerberosUtility.py is a utility to handler kerberos things.
|
|
#############################################################################
|
|
import gc
|
|
import sys
|
|
import os
|
|
import getopt
|
|
import subprocess
|
|
import shutil
|
|
import pwd
|
|
from subprocess import PIPE
|
|
|
|
sys.path.append(sys.path[0] + "/../")
|
|
from gspylib.common.DbClusterInfo import dbClusterInfo
|
|
from gspylib.common.Common import DefaultValue
|
|
from gspylib.common.GaussLog import GaussLog
|
|
from gspylib.common.ErrorCode import ErrorCode
|
|
from gspylib.threads.SshTool import SshTool
|
|
from multiprocessing.dummy import Pool as ThreadPool
|
|
from domain_utils.cluster_file.cluster_config_file import ClusterConfigFile
|
|
from base_utils.os.cmd_util import CmdUtil
|
|
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 base_utils.os.net_util import NetUtil
|
|
from base_utils.common.fast_popen import FastPopen
|
|
from domain_utils.domain_common.cluster_constants import ClusterConstants
|
|
from domain_utils.security.random_value import RandomValue
|
|
|
|
METHOD_TRUST = "trust"
|
|
g_ignorepgHbaMiss = True
|
|
g_clusterInfo = None
|
|
#write /etc/hosts kerberos flag
|
|
VALUE_LIST = ["PGKRBSRVNAME", "KRBHOSTNAME", "MPPDB_KRB5_FILE_PATH",
|
|
"KRB5RCACHETYPE"]
|
|
SERVER_ENV_LIST = ["KRB_HOME", "KRB5_CONFIG", "KRB5_KDC_PROFILE"]
|
|
|
|
g_logger = None
|
|
g_opts = None
|
|
g_sshTool = None
|
|
|
|
|
|
class CmdOptions():
|
|
"""
|
|
install the cluster on local node
|
|
"""
|
|
def __init__(self):
|
|
self.action = ""
|
|
self.user = ""
|
|
self.mpprcFile = ""
|
|
self.clusterInfo = None
|
|
self.principal = ""
|
|
self.keytab = ""
|
|
self.dbNodeInfo = None
|
|
self.krbHomePath = ""
|
|
self.krbConfigPath = ""
|
|
self.server = False
|
|
self.client = False
|
|
self.gausshome = ""
|
|
self.gausshome_kerberso = ""
|
|
|
|
|
|
def initGlobals():
|
|
"""
|
|
init global variables
|
|
input : NA
|
|
output: NA
|
|
"""
|
|
global g_opts
|
|
logFile = ClusterLog.getOMLogPath(ClusterConstants.LOCAL_LOG_FILE,
|
|
g_opts.user, "")
|
|
|
|
# Init logger
|
|
global g_logger
|
|
g_logger = GaussLog(logFile, "KerberosUtility")
|
|
|
|
global g_clusterInfo
|
|
# init for clusterInfo
|
|
g_clusterInfo = dbClusterInfo()
|
|
g_clusterInfo.initFromStaticConfig(g_opts.user)
|
|
g_logger.debug("Cluster information: \n%s." % str(g_clusterInfo))
|
|
|
|
global g_sshTool
|
|
nodenames = g_clusterInfo.getClusterNodeNames()
|
|
g_sshTool = SshTool(nodenames)
|
|
|
|
try:
|
|
# init for __clusterInfo and __dbNodeInfo
|
|
g_opts.clusterInfo = g_clusterInfo
|
|
hostName = NetUtil.GetHostIpOrName()
|
|
g_opts.dbNodeInfo = g_clusterInfo.getDbNodeByName(hostName)
|
|
|
|
#get env variable file
|
|
g_opts.mpprcFile = EnvUtil.getMpprcFile()
|
|
|
|
# create kerberso directory under GAUSSHOME
|
|
gausshome = ClusterDir.getInstallDir(g_opts.user)
|
|
if not gausshome:
|
|
raise Exception(ErrorCode.GAUSS_518["GAUSS_51802"] % "GAUSSHOME")
|
|
g_opts.gausshome = gausshome
|
|
g_opts.gausshome_kerberso = os.path.join(gausshome, "kerberos")
|
|
if not os.path.isdir(g_opts.gausshome_kerberso):
|
|
dir_permission = 0o700
|
|
os.makedirs(g_opts.gausshome_kerberso, mode=dir_permission)
|
|
|
|
if g_opts.action == "install" and g_opts.server:
|
|
g_logger.debug("%s the kerberos server.", g_opts.action)
|
|
|
|
else:
|
|
if g_opts.action == "uninstall":
|
|
g_logger.debug("%s the kerberos tool.", g_opts.action)
|
|
else:
|
|
g_logger.debug("%s the kerberos client.", g_opts.action)
|
|
tablespace = EnvUtil.getEnv("ELK_SYSTEM_TABLESPACE")
|
|
if tablespace is not None and tablespace != "":
|
|
xmlfile = os.path.join(os.path.dirname(g_opts.mpprcFile),
|
|
DefaultValue.FI_ELK_KRB_XML)
|
|
else:
|
|
xmlfile = os.path.join(os.path.dirname(g_opts.mpprcFile),
|
|
DefaultValue.FI_KRB_XML)
|
|
xmlfile = os.path.realpath(xmlfile)
|
|
if not os.path.isfile(xmlfile):
|
|
raise Exception(ErrorCode.GAUSS_502["GAUSS_50201"] % xmlfile)
|
|
|
|
rootNode = ClusterConfigFile.initParserXMLFile(xmlfile)
|
|
elementArray = rootNode.findall("property")
|
|
|
|
for element in elementArray:
|
|
if (element.find('name').text == "mppdb.kerberos.principal"
|
|
or element.find('name').text == "elk.kerberos.principal"):
|
|
g_opts.principal = element.find('value').text
|
|
if (element.find('name').text == "mppdb.kerberos.keytab"
|
|
or element.find('name').text == "elk.kerberos.keytab"):
|
|
g_opts.keytab = element.find('value').text
|
|
if (element.find('name').text == 'KRB_HOME'):
|
|
g_opts.krbHomePath = element.find('value').text
|
|
if (element.find('name').text == 'KRB_CONFIG'):
|
|
g_opts.krbConfigPath = element.find('value').text
|
|
|
|
if(g_opts.principal == "" or g_opts.keytab == ""
|
|
or g_opts.krbHomePath == "" or g_opts.krbConfigPath == ""):
|
|
raise Exception(ErrorCode.GAUSS_512["GAUSS_51200"] %
|
|
"mppdb.kerberos.principal or "
|
|
"mppdb.kerberos.keytab"
|
|
" or KRB_HOME or KRB_CONFIG"
|
|
+ " The xml file is %s." % xmlfile)
|
|
|
|
except Exception as e:
|
|
g_logger.logExit(str(e))
|
|
g_logger.debug("Instance information on local node:\n%s."
|
|
% str(g_opts.dbNodeInfo))
|
|
|
|
|
|
class Kerberos():
|
|
def __init__(self):
|
|
self.__dbNodeInfo = None
|
|
self.__allIps = []
|
|
self.__cooConfig = {}
|
|
self.__dataConfig = {}
|
|
self.__gtmConfig = {}
|
|
self.__cmsConfig = {}
|
|
self.__IpStringList = []
|
|
self.__DNStringList = []
|
|
|
|
def __rollback(self, isServer):
|
|
g_logger.log("An error happened in executing the command, "
|
|
"begin rollback work...")
|
|
if isServer:
|
|
self.__rollbackServerInstall()
|
|
else:
|
|
self.__uninstall(True)
|
|
g_logger.log("rollback work complete.")
|
|
|
|
def __rollbackServerInstall(self):
|
|
if os.path.isdir(g_opts.gausshome_kerberso):
|
|
shutil.rmtree(g_opts.gausshome_kerberso)
|
|
self.__clearEnvironmentVariableValue(True)
|
|
self.__cleanAuthConfig()
|
|
self.__cleanServer()
|
|
|
|
|
|
def __triggerJob(self, isUninstall, isServer=False):
|
|
'''
|
|
function: triggerJob for call kinit
|
|
'''
|
|
if(not isUninstall):
|
|
g_logger.log("start triggerJob.")
|
|
if isServer:
|
|
self.__initUser()
|
|
self.__startServer()
|
|
self.__distributeKeyAndSite()
|
|
self.__setServiceCron()
|
|
else:
|
|
self.__executeJob()
|
|
g_logger.log("successfully start triggerJob.")
|
|
else:
|
|
g_logger.log("stop triggerJob.")
|
|
self.__cancelCron()
|
|
g_logger.log("successfully stop triggerJob.")
|
|
|
|
def __clearEnvironmentVariableValue(self, isServer=False):
|
|
"""
|
|
function: clear kerberos EnvironmentVariable
|
|
input: isServer
|
|
output: NA
|
|
"""
|
|
for value in VALUE_LIST:
|
|
cmd = "sed -i -e '/^.*%s=/d' '%s'" % (value, g_opts.mpprcFile)
|
|
(status, output) = subprocess.getstatusoutput(cmd)
|
|
if status != 0:
|
|
raise Exception(ErrorCode.GAUSS_514["GAUSS_51400"] % cmd
|
|
+ "Error:\n%s" % output)
|
|
if isServer:
|
|
for value in SERVER_ENV_LIST:
|
|
cmd = "sed -i -e '/^.*%s=/d' '%s' && " \
|
|
"sed -i -e '/^.*PATH=\$%s/d' '%s' && " \
|
|
"sed -i -e '/^.*LD_LIBRARY_PATH=\$%s/d' '%s'" % \
|
|
(value, g_opts.mpprcFile, value, g_opts.mpprcFile,
|
|
value, g_opts.mpprcFile)
|
|
(status, output) = subprocess.getstatusoutput(cmd)
|
|
if(status != 0):
|
|
raise Exception(ErrorCode.GAUSS_514["GAUSS_51400"] % cmd
|
|
+ "Error:\n%s" % output)
|
|
|
|
g_logger.log("successfully clear kerberos env Variables.")
|
|
|
|
def __setUserEnvVariable(self, isUninstall, isServer=False,
|
|
isRollBack=False):
|
|
'''
|
|
function: set user env Variable
|
|
'''
|
|
g_logger.log("start set user env Variable.")
|
|
if(not isUninstall):
|
|
try:
|
|
if isServer:
|
|
self.__clearEnvironmentVariableValue(True)
|
|
|
|
# SET variable KRB_HOME
|
|
cmd = "echo \"export KRB_HOME=%s\" >> %s" % \
|
|
(g_opts.gausshome, g_opts.mpprcFile)
|
|
(status, output) = subprocess.getstatusoutput(cmd)
|
|
if (status != 0):
|
|
raise Exception(ErrorCode.GAUSS_518["GAUSS_51804"] %
|
|
"KRB_HOME" + output
|
|
+ "\nThe cmd is %s " % cmd)
|
|
g_logger.log("Config environment variable KRB_HOME "
|
|
"successfully.")
|
|
|
|
# SET variable KRB5_CONFIG
|
|
cmd = "echo \"export KRB5_CONFIG=%s/krb5.conf\" >> %s" % \
|
|
(g_opts.gausshome_kerberso, g_opts.mpprcFile)
|
|
(status, output) = subprocess.getstatusoutput(cmd)
|
|
if (status != 0):
|
|
raise Exception(ErrorCode.GAUSS_518["GAUSS_51804"] %
|
|
"KRB5_CONFIG" + output
|
|
+ "\nThe cmd is %s " % cmd)
|
|
g_logger.log("Config environment variable KRB5_CONFIG "
|
|
"successfully.")
|
|
|
|
# SET variable KRB5_KDC_PROFILE
|
|
cmd = "echo \"export KRB5_KDC_PROFILE=%s/kdc.conf\" " \
|
|
">> %s" \
|
|
% (g_opts.gausshome_kerberso, g_opts.mpprcFile)
|
|
(status, output) = subprocess.getstatusoutput(cmd)
|
|
if (status != 0):
|
|
raise Exception(ErrorCode.GAUSS_518["GAUSS_51804"] %
|
|
"KRB5_KDC_PROFILE" + output
|
|
+ "\nThe cmd is %s " % cmd)
|
|
g_logger.log("Config environment "
|
|
"variable KRB5_KDC_PROFILE successfully.")
|
|
|
|
# SET variable PATH
|
|
cmd = "echo \"export PATH=\$KRB_HOME/bin:\$PATH\" " \
|
|
">> %s" % (g_opts.mpprcFile)
|
|
(status, output) = subprocess.getstatusoutput(cmd)
|
|
if (status != 0):
|
|
raise Exception(ErrorCode.GAUSS_518["GAUSS_51804"] %
|
|
"PATH" + output
|
|
+ "\nThe cmd is %s " % cmd)
|
|
g_logger.log("Config environment variable PATH "
|
|
"successfully.")
|
|
|
|
# SET variable LD_LIBRARY_PATH
|
|
cmd = "echo \"export LD_LIBRARY_PATH=\$KRB_HOME/lib:" \
|
|
"\$LD_LIBRARY_PATH\" >> %s" % (g_opts.mpprcFile)
|
|
(status, output) = subprocess.getstatusoutput(cmd)
|
|
if (status != 0):
|
|
raise Exception(ErrorCode.GAUSS_518["GAUSS_51804"] %
|
|
"LD_LIBRARY_PATH" + output
|
|
+ "\nThe cmd is %s " % cmd)
|
|
g_logger.log("Config environment variable LD_LIBRARY_PATH "
|
|
"successfully.")
|
|
|
|
else:
|
|
# get principal
|
|
principals = g_opts.principal.split("/")
|
|
if (len(g_opts.principal.split('/')) < 2):
|
|
raise Exception(ErrorCode.GAUSS_500["GAUSS_50009"]
|
|
+ "principal: %s" % g_opts.principal)
|
|
address = g_opts.principal.split('/')[1].split('@')[0]
|
|
|
|
self.__clearEnvironmentVariableValue()
|
|
# SET variable KRB5_CONFIG
|
|
cmd = "echo \"export MPPDB_KRB5_FILE_PATH=%s/krb5.conf\"" \
|
|
" >> %s" % (os.path.dirname(g_opts.mpprcFile),
|
|
g_opts.mpprcFile)
|
|
(status, output) = subprocess.getstatusoutput(cmd)
|
|
if (status != 0):
|
|
raise Exception(ErrorCode.GAUSS_514["GAUSS_51400"]
|
|
% cmd + "Error:\n%s." % output)
|
|
g_logger.log("Config environment variable KRB5_CONFIG "
|
|
"successfully.")
|
|
# SET variable PGKRBSRVNAME
|
|
|
|
cmd = "echo \"export PGKRBSRVNAME=%s\" >>%s" % \
|
|
(principals[0], g_opts.mpprcFile)
|
|
|
|
(status, output) = subprocess.getstatusoutput(cmd)
|
|
if (status != 0):
|
|
raise Exception(ErrorCode.GAUSS_514["GAUSS_51400"]
|
|
% cmd + "Error:\n%s." % output)
|
|
g_logger.log("Config environment variable PGKRBSRVNAME "
|
|
"successfully.")
|
|
# SET variable KRBHOSTNAME
|
|
|
|
cmd = "echo \"export KRBHOSTNAME=%s\" >>%s" % \
|
|
(address, g_opts.mpprcFile)
|
|
|
|
(status, output) = subprocess.getstatusoutput(cmd)
|
|
if status != 0:
|
|
raise Exception(ErrorCode.GAUSS_514["GAUSS_51400"]
|
|
% cmd + "Error:\n%s." % output)
|
|
g_logger.log("Config environment variable KRBHOSTNAME "
|
|
"successfully.")
|
|
# SET variable KRB5RCACHETYPE
|
|
cmd = "echo \"export KRB5RCACHETYPE=none\" >>%s" % \
|
|
(g_opts.mpprcFile)
|
|
(status, output) = subprocess.getstatusoutput(cmd)
|
|
if status != 0:
|
|
raise Exception(ErrorCode.GAUSS_514["GAUSS_51400"]
|
|
% cmd + "Error:\n%s." % output)
|
|
|
|
# SET KRB5_CONFIG
|
|
cmd = "echo \"export KRB5_CONFIG=%s/krb5.conf\"" \
|
|
" >> %s" % (os.path.dirname(g_opts.mpprcFile),
|
|
g_opts.mpprcFile)
|
|
(status, output) = subprocess.getstatusoutput(cmd)
|
|
if status != 0:
|
|
raise Exception(ErrorCode.GAUSS_514["GAUSS_51400"] %
|
|
cmd + "Error:\n%s." % output)
|
|
g_logger.log("Config environment variable KRB5RCACHETYPE "
|
|
"successfully.")
|
|
except Exception as e:
|
|
raise Exception(ErrorCode.GAUSS_518["GAUSS_51804"]
|
|
% "" + "Error:%s." % str(e))
|
|
else:
|
|
if isRollBack:
|
|
self.__clearEnvironmentVariableValue(False)
|
|
else:
|
|
self.__clearEnvironmentVariableValue(True)
|
|
|
|
def __configPostgresql(self, isUninstall):
|
|
'''
|
|
function: set config postgresql file
|
|
'''
|
|
g_logger.log("start set config postgresql file")
|
|
|
|
instanceList = []
|
|
if(not isUninstall):
|
|
self.__cooConfig["krb_server_keyfile"] = "'" + g_opts.keytab + "'"
|
|
self.__dataConfig["krb_server_keyfile"] = "'" + g_opts.keytab + "'"
|
|
self.__gtmConfig["gtm_authentication_type"] = "gss"
|
|
self.__gtmConfig["gtm_krb_server_keyfile"] = "'" + g_opts.keytab \
|
|
+ "'"
|
|
self.__cmsConfig["cm_auth_method"] = "gss"
|
|
self.__cmsConfig["cm_krb_server_keyfile"] = "'" + g_opts.keytab + \
|
|
"'"
|
|
else:
|
|
self.__cooConfig["krb_server_keyfile"] = ""
|
|
self.__dataConfig["krb_server_keyfile"] = ""
|
|
self.__gtmConfig["gtm_authentication_type"] = "trust"
|
|
self.__gtmConfig["gtm_krb_server_keyfile"] = "''"
|
|
self.__cmsConfig["cm_auth_method"] = "trust"
|
|
self.__cmsConfig["cm_krb_server_keyfile"] = "''"
|
|
|
|
# get coordinators instance
|
|
for cooInst in g_opts.dbNodeInfo.coordinators:
|
|
instanceList.append(cooInst)
|
|
# get datanode instance
|
|
for dnInst in g_opts.dbNodeInfo.datanodes:
|
|
instanceList.append(dnInst)
|
|
# get gtm instance
|
|
for gtmInst in g_opts.dbNodeInfo.gtms:
|
|
instanceList.append(gtmInst)
|
|
# get cms instance
|
|
for cmsInst in g_opts.dbNodeInfo.cmservers:
|
|
instanceList.append(cmsInst)
|
|
|
|
if(len(instanceList) == 0):
|
|
return
|
|
try:
|
|
#config instance in paralle
|
|
pool = ThreadPool(DefaultValue.getCpuSet())
|
|
pool.map(self.__configInst, instanceList)
|
|
pool.close()
|
|
pool.join()
|
|
except Exception as e:
|
|
raise Exception(str(e))
|
|
g_logger.log("successfully set config postgresql file")
|
|
|
|
def __configPgHba(self, isUninstall):
|
|
'''
|
|
set pg_hba.conf file
|
|
'''
|
|
g_logger.log("start config pg_hba file")
|
|
try:
|
|
# get current node information
|
|
hostName = NetUtil.GetHostIpOrName()
|
|
self.__dbNodeInfo = g_clusterInfo.getDbNodeByName(hostName)
|
|
if (self.__dbNodeInfo is None):
|
|
raise Exception(ErrorCode.GAUSS_516["GAUSS_51620"] % "local"
|
|
+ " There is no host named %s." % hostName)
|
|
#getall node names
|
|
nodenames = g_clusterInfo.getClusterNodeNames()
|
|
for nodename in nodenames:
|
|
nodeinfo = g_clusterInfo.getDbNodeByName(nodename)
|
|
self.__allIps += nodeinfo.backIps
|
|
self.__allIps += nodeinfo.sshIps
|
|
for inst in nodeinfo.cmservers:
|
|
self.__allIps += inst.haIps
|
|
self.__allIps += inst.listenIps
|
|
for inst in nodeinfo.coordinators:
|
|
self.__allIps += inst.haIps
|
|
self.__allIps += inst.listenIps
|
|
for inst in nodeinfo.datanodes:
|
|
self.__allIps += inst.haIps
|
|
self.__allIps += inst.listenIps
|
|
for inst in nodeinfo.gtms:
|
|
self.__allIps += inst.haIps
|
|
self.__allIps += inst.listenIps
|
|
# set local ip 127.0.0.1
|
|
self.__allIps += ['127.0.0.1']
|
|
# get all ips. Remove the duplicates ips
|
|
self.__allIps = DefaultValue.Deduplication(self.__allIps)
|
|
# build ip string list
|
|
#set Kerberos ip
|
|
principals = g_opts.principal.split("/")
|
|
principals = principals[1].split("@")
|
|
# Every 1000 records merged into one"
|
|
ipstring = ""
|
|
for ip in self.__allIps:
|
|
if not isUninstall:
|
|
ipstring += " -h 'host all all " \
|
|
" %s/32 gss " \
|
|
"include_realm=1 krb_realm=%s'" % \
|
|
(ip, principals[1])
|
|
else:
|
|
ipstring += " -h 'host all all " \
|
|
" %s/32 %s'" % (ip, METHOD_TRUST)
|
|
if ipstring != "":
|
|
self.__IpStringList.append(ipstring)
|
|
#write config hba
|
|
self.__writeConfigHba()
|
|
except Exception as e:
|
|
raise Exception(ErrorCode.GAUSS_530["GAUSS_53024"]
|
|
+ "Error:%s." % str(e))
|
|
|
|
g_logger.debug("Instance information about local node:\n%s." %
|
|
str(self.__dbNodeInfo))
|
|
g_logger.log("successfully config pg_hba file")
|
|
|
|
def __configDNPgHba(self, isUninstall):
|
|
'''
|
|
set DN pg_hba.conf file for replication channel
|
|
'''
|
|
g_logger.log("start config pg_hba file for database node replication "
|
|
"channel")
|
|
try:
|
|
principals = g_opts.principal.split("/")
|
|
principals = principals[1].split("@")
|
|
ipstring = ""
|
|
if (not isUninstall):
|
|
ipstring += " -h 'host replication %s " \
|
|
" ::1/128 gss include_realm=1" \
|
|
" krb_realm=%s'" % \
|
|
(g_opts.user, principals[1])
|
|
else:
|
|
ipstring += " -h 'host replication %s " \
|
|
" ::1/128 %s'" % \
|
|
(g_opts.user, METHOD_TRUST)
|
|
if (ipstring != ""):
|
|
self.__DNStringList.append(ipstring)
|
|
self.__writeDNConfigHba()
|
|
except Exception as e:
|
|
raise Exception(ErrorCode.GAUSS_502["GAUSS_50205"]
|
|
% ("database node config for pg_hba.conf. %s"
|
|
% str(e)))
|
|
g_logger.log("successfully config pg_hba file for database node "
|
|
"replication channel")
|
|
|
|
def __configInst(self, dbInst):
|
|
"""
|
|
function: Modify a parameter of postgresql.conf
|
|
input : typename, datadir, configFile, parmeterDict
|
|
output: NA
|
|
"""
|
|
configFile = os.path.join(dbInst.datadir, "postgresql.conf")
|
|
if (dbInst.instanceRole != DefaultValue.INSTANCE_ROLE_GTM and
|
|
dbInst.instanceRole != DefaultValue.INSTANCE_ROLE_CMSERVER and
|
|
not os.path.isfile(configFile)):
|
|
return
|
|
if dbInst.instanceRole == DefaultValue.INSTANCE_ROLE_COODINATOR:
|
|
# modifying CN configuration.
|
|
g_logger.log("Modify CN %s configuration." % dbInst.instanceId)
|
|
configFile = os.path.join(dbInst.datadir, "postgresql.conf")
|
|
# Set default value for each inst
|
|
tempCommonDict = self.__cooConfig
|
|
self.__setConfigItem(DefaultValue.INSTANCE_ROLE_COODINATOR,
|
|
dbInst.datadir, tempCommonDict)
|
|
|
|
if dbInst.instanceRole == DefaultValue.INSTANCE_ROLE_DATANODE:
|
|
# modifying database node configuration.
|
|
g_logger.log("Modify database node %s configuration."
|
|
% dbInst.instanceId)
|
|
# Set default value for each inst
|
|
tempCommonDict = self.__dataConfig
|
|
try:
|
|
self.__setConfigItem(DefaultValue.INSTANCE_ROLE_DATANODE,
|
|
dbInst.datadir, tempCommonDict)
|
|
except Exception as e:
|
|
raise Exception(str(e))
|
|
|
|
if dbInst.instanceRole == DefaultValue.INSTANCE_ROLE_GTM:
|
|
# modifying GTM configuration.
|
|
g_logger.log("Modify GTM %s configuration." % dbInst.instanceId)
|
|
# Set default value for each inst
|
|
tempCommonDict = self.__gtmConfig
|
|
try:
|
|
self.__setConfigItem(DefaultValue.INSTANCE_ROLE_GTM,
|
|
dbInst.datadir, tempCommonDict)
|
|
except Exception as e:
|
|
raise Exception(str(e))
|
|
|
|
if dbInst.instanceRole == DefaultValue.INSTANCE_ROLE_CMSERVER:
|
|
# modifying CMSERVER configuration.
|
|
g_logger.log("Modify CMserver %s configuration."
|
|
% dbInst.instanceId)
|
|
# Set default value for each inst
|
|
tempCommonDict = self.__cmsConfig
|
|
try:
|
|
self.__setConfigItem(DefaultValue.INSTANCE_ROLE_CMSERVER,
|
|
dbInst.datadir, tempCommonDict)
|
|
except Exception as e:
|
|
raise Exception(str(e))
|
|
|
|
def __setConfigItem(self, typename, datadir, parmeterDict):
|
|
"""
|
|
function: Modify a parameter
|
|
input : typename, datadir, parmeterDict
|
|
output: NA
|
|
"""
|
|
# build GUC parameter string
|
|
gucstr = ""
|
|
for entry in list(parmeterDict.items()):
|
|
if entry[1] == "":
|
|
gucstr += " -c \"%s=\'\'\"" % (entry[0])
|
|
else:
|
|
gucstr += " -c \"%s=%s\"" % (entry[0], entry[1])
|
|
# check the GUC parameter string
|
|
if gucstr == "":
|
|
return
|
|
inst_type_map = {DefaultValue.INSTANCE_ROLE_DATANODE:"datanode",
|
|
DefaultValue.INSTANCE_ROLE_COODINATOR:"coordinator",
|
|
DefaultValue.INSTANCE_ROLE_CMSERVER:"cmserver"}
|
|
inst_type = " -Z %s"%inst_type_map.get(typename) if inst_type_map.get(typename) else ""
|
|
if typename == DefaultValue.INSTANCE_ROLE_DATANODE or \
|
|
typename == DefaultValue.INSTANCE_ROLE_COODINATOR:
|
|
cmd = "source '%s'; gs_guc set -D %s %s" % \
|
|
(g_opts.mpprcFile, datadir, gucstr)
|
|
DefaultValue.retry_gs_guc(cmd)
|
|
if self.__gsdbStatus():
|
|
cmd = "source '%s'; gs_guc reload -D %s %s" % \
|
|
(g_opts.mpprcFile, datadir, gucstr)
|
|
try:
|
|
DefaultValue.retry_gs_guc(cmd)
|
|
except Exception as e:
|
|
raise Exception(str(e))
|
|
else:
|
|
cmd = "source '%s'; gs_guc set %s -N all -I all %s" % \
|
|
(g_opts.mpprcFile, inst_type, gucstr)
|
|
DefaultValue.retry_gs_guc(cmd)
|
|
|
|
def __gsdbStatus(self):
|
|
"""
|
|
function: get gaussdb process
|
|
input: NA
|
|
output: True/False
|
|
"""
|
|
cmd = "ps ux | grep -v '\<grep\>' | grep '%s/bin/gaussdb'" % \
|
|
g_clusterInfo.appPath
|
|
(status, output) = subprocess.getstatusoutput(cmd)
|
|
if status != 0 and output:
|
|
raise Exception("Get gaussdb process failed." +
|
|
"The cmd is %s " % cmd)
|
|
if output:
|
|
return True
|
|
return False
|
|
|
|
def __writeConfigHba(self):
|
|
"""
|
|
function: set hba config
|
|
input : NA
|
|
output: NA
|
|
"""
|
|
instances = self.__dbNodeInfo.datanodes + \
|
|
self.__dbNodeInfo.coordinators
|
|
#Determine whether this node containing CN, DN instance
|
|
if(len(instances) == 0):
|
|
g_logger.debug("The count number of coordinator and "
|
|
"datanode on local node is zero.")
|
|
return
|
|
try:
|
|
pool = ThreadPool(DefaultValue.getCpuSet())
|
|
pool.map(self.__configAnInstance, instances)
|
|
pool.close()
|
|
pool.join()
|
|
except Exception as e:
|
|
raise Exception(str(e))
|
|
|
|
def __writeDNConfigHba(self):
|
|
"""
|
|
function: set hba config for dn replication channel
|
|
input : NA
|
|
output: NA
|
|
"""
|
|
instances = self.__dbNodeInfo.datanodes
|
|
if (len(instances) == 0):
|
|
g_logger.debug("The count number of datanode "
|
|
"on local node is zero.")
|
|
return
|
|
try:
|
|
pool = ThreadPool(DefaultValue.getCpuSet())
|
|
pool.map(self.__configAnInstanceHA, instances)
|
|
pool.close()
|
|
pool.join()
|
|
except Exception as e:
|
|
raise Exception(str(e))
|
|
|
|
def __configAnInstance(self, instance):
|
|
# check instance data directory
|
|
if (instance.datadir == "" or not os.path.isdir(instance.datadir)):
|
|
if(g_ignorepgHbaMiss):
|
|
g_logger.debug("Failed to obtain data directory of "
|
|
"the instance[%s]." % str(instance))
|
|
return
|
|
else:
|
|
raise Exception(ErrorCode.GAUSS_502["GAUSS_50219"] %
|
|
("data directory of the instance[%s]" %
|
|
str(instance)))
|
|
# check pg_hba.conf
|
|
hbaFile = "%s/pg_hba.conf" % instance.datadir
|
|
if(g_ignorepgHbaMiss and not os.path.isfile(hbaFile)):
|
|
g_logger.debug("The %s does not exist." % hbaFile)
|
|
return
|
|
# do gs_guc to add host into pg_hba.conf
|
|
self.__addHostToFile(instance.datadir)
|
|
|
|
def __configAnInstanceHA(self, instance):
|
|
instanceRole = "datanode"
|
|
# check instance data directory
|
|
if (instance.datadir == "" or not os.path.isdir(instance.datadir)):
|
|
if(g_ignorepgHbaMiss):
|
|
g_logger.debug("Failed to obtain data directory "
|
|
"of the instance[%s]." % str(instance))
|
|
return
|
|
else:
|
|
raise Exception(ErrorCode.GAUSS_502["GAUSS_50219"] %
|
|
("data directory of the instance[%s]"
|
|
% str(instance)))
|
|
# check pg_hba.conf
|
|
hbaFile = "%s/pg_hba.conf" % instance.datadir
|
|
if(g_ignorepgHbaMiss and not os.path.isfile(hbaFile)):
|
|
g_logger.debug("The %s does not exist." % hbaFile)
|
|
return
|
|
# do gs_guc to add host into pg_hba.conf
|
|
self.__addDNhostToFile(instanceRole, instance.datadir)
|
|
|
|
def __addHostToFile(self, instanceDataPath):
|
|
# do gs_guc to add host into pg_hba.conf
|
|
for IpString in self.__IpStringList:
|
|
cmd = "source '%s';gs_guc set -D %s %s" % (g_opts.mpprcFile,
|
|
instanceDataPath,
|
|
IpString)
|
|
DefaultValue.retry_gs_guc(cmd)
|
|
|
|
def __addDNhostToFile(self, dbInstanceRole, instanceDataPath):
|
|
"""
|
|
function: set DN config postgresql file for replication channel
|
|
input:dbInstanceRole, instanceDataPath
|
|
output:NA
|
|
"""
|
|
if (dbInstanceRole == "datanode"):
|
|
for IpDNString in self.__DNStringList:
|
|
cmd = "source '%s';gs_guc set -D %s %s" % \
|
|
(g_opts.mpprcFile, instanceDataPath, IpDNString)
|
|
DefaultValue.retry_gs_guc(cmd)
|
|
|
|
def __executeJob(self):
|
|
"""
|
|
function:call TGT from kinit's tool
|
|
input:NA
|
|
output:NA
|
|
"""
|
|
try:
|
|
kinitPath = "%s/bin/kinit" % g_opts.krbHomePath
|
|
kcmd = 'export LD_LIBRARY_PATH=%s/lib:$LD_LIBRARY_PATH;' \
|
|
'export KRB5_CONFIG=$MPPDB_KRB5_FILE_PATH;%s -k -t %s %s' \
|
|
% (g_opts.krbHomePath, kinitPath,
|
|
g_opts.keytab, g_opts.principal)
|
|
cmd = 'source %s; %s' % (g_opts.mpprcFile, kcmd)
|
|
(status, output) = CmdUtil.retryGetstatusoutput(cmd)
|
|
if(status != 0):
|
|
raise Exception(ErrorCode.GAUSS_514["GAUSS_51400"] % cmd
|
|
+ " Output: \n%s" % str(output))
|
|
g_logger.debug("Get ticket successfully.")
|
|
#set cron
|
|
self.__setCron()
|
|
except Exception as e:
|
|
raise Exception("Call TGT from kinit's tool: %s." % cmd +
|
|
" Exception: \n%s" % str(e))
|
|
|
|
def __setCron(self):
|
|
"""
|
|
function: Set linux cron
|
|
input : NA
|
|
output: NA
|
|
"""
|
|
g_logger.log("Set CRON.")
|
|
cronFile = "%s/gauss_cron_%d" % \
|
|
(EnvUtil.getTmpDirFromEnv(g_opts.user), os.getpid())
|
|
setCronCmd = "crontab -l > %s && " % cronFile
|
|
setCronCmd += "sed -i '/^.*kinit.*$/d' '%s'; " % cronFile
|
|
setCronCmd += '''echo '*/1 * * * * source '%s';''' \
|
|
'''export LD_LIBRARY_PATH='%s'/lib:$LD_LIBRARY_PATH;''' \
|
|
'''export KRB5_CONFIG=$MPPDB_KRB5_FILE_PATH ''' % \
|
|
(g_opts.mpprcFile, g_opts.krbHomePath)
|
|
setCronCmd += '''klistcmd="'%s'/bin/klist";''' % (g_opts.krbHomePath)
|
|
setCronCmd += '''kinitcmd="'%s'/bin/kinit -k -t %s %s ";''' % \
|
|
(g_opts.krbHomePath, g_opts.keytab, g_opts.principal)
|
|
setCronCmd += '''klistresult=`$klistcmd>>/dev/null 2>&1;echo $?`;'''
|
|
setCronCmd += '''if [ $klistresult -ne 0 ];then `$kinitcmd`;else ''' \
|
|
'''expiresTime=`$klistcmd|grep krbtgt|awk -F " " ''' \
|
|
'''"{print \\\\\\$2}"`;startTime=`$klistcmd|grep ''' \
|
|
'''krbtgt|awk -F " " "{print \\\\\\$1}"`;''' \
|
|
'''currentTime=`date +\%%s`;currentTime=''' \
|
|
'''`date +\%%s`;if [ $[`date -d "$expiresTime"''' \
|
|
''' +\%%s`-$currentTime] -le 300 ] || [ $[`date -d''' \
|
|
''' "$startTime" +\%%s`-$currentTime] -ge 0 ];''' \
|
|
'''then `$kinitcmd`;fi;fi;>>/dev/null 2>&1''' \
|
|
'''& ' >> %s ;''' % (cronFile)
|
|
setCronCmd += "crontab %s&&" % cronFile
|
|
setCronCmd += "rm -f '%s'" % cronFile
|
|
|
|
g_logger.debug("Command for setting CRON: %s" % setCronCmd)
|
|
(status, output) = subprocess.getstatusoutput(setCronCmd)
|
|
if(status != 0):
|
|
raise Exception(ErrorCode.GAUSS_508["GAUSS_50801"]
|
|
+ " Error: \n%s." % str(output)
|
|
+ "The cmd is %s " % setCronCmd)
|
|
|
|
cmd = "source %s;export LD_LIBRARY_PATH=%s/lib:$LD_LIBRARY_PATH;" \
|
|
"export KRB5_CONFIG=$MPPDB_KRB5_FILE_PATH;" % \
|
|
(g_opts.mpprcFile, g_opts.krbHomePath)
|
|
cmd += "klistcmd='%s/bin/klist';" % (g_opts.krbHomePath)
|
|
cmd += "kinitcmd='%s/bin/kinit -k -t %s %s';" % \
|
|
(g_opts.krbHomePath, g_opts.keytab, g_opts.principal)
|
|
cmd += "klistresult=`$klistcmd>>/dev/null 2>&1;echo $?`;"
|
|
cmd += "if [ $klistresult -ne 0 ];then `$kinitcmd`;" \
|
|
"else expiresTime=`$klistcmd|grep krbtgt|" \
|
|
"awk -F ' ' '{print \$2}'`;" \
|
|
"startTime=`$klistcmd|grep krbtgt|awk -F ' ' '{print \$1}'`;" \
|
|
"currentTime=`date +\%s`;currentTime=`date +\%s`;" \
|
|
"if [ $[`date -d $expiresTime +\%s`-$currentTime] -le 300 ] " \
|
|
"|| [ $[`date -d $startTime +\%s`-$currentTime] -ge 0 ];" \
|
|
"then `$kinitcmd`;fi;fi;>>/dev/null 2>&1"
|
|
(status, output) = subprocess.getstatusoutput(cmd)
|
|
if(status != 0):
|
|
raise Exception(ErrorCode.GAUSS_514["GAUSS_51400"] % cmd +
|
|
"Error:\n%s" % str(output))
|
|
|
|
g_logger.log("Successfully Set CRON.")
|
|
|
|
|
|
def __setServiceCron(self):
|
|
g_logger.log("Set CRON.")
|
|
cronFile = "%s/gauss_cron_%d" % \
|
|
(EnvUtil.getTmpDirFromEnv(g_opts.user), os.getpid())
|
|
setCronCmd = "crontab -l > %s && " % cronFile
|
|
setCronCmd += "sed -i '/^.*krb5kdc.*$/d' '%s'; " % cronFile
|
|
setCronCmd += '''echo "*/1 * * * * source %s; ''' \
|
|
'''kdc_pid_list=\`ps ux | grep -E krb5kdc| ''' \
|
|
'''grep -v grep | awk '{print \\\\\\$2}'\` && ''' \
|
|
'''(if [ X\"\$kdc_pid_list\" == X\"\" ]; ''' \
|
|
'''then krb5kdc; fi) " >> %s; ''' % \
|
|
(g_opts.mpprcFile, cronFile)
|
|
setCronCmd += "crontab %s && " % cronFile
|
|
setCronCmd += "rm -f '%s'" % cronFile
|
|
|
|
g_logger.debug("Command for setting CRON: %s" % setCronCmd)
|
|
(status, output) = subprocess.getstatusoutput(setCronCmd)
|
|
if(status != 0):
|
|
raise Exception(ErrorCode.GAUSS_508["GAUSS_50801"]
|
|
+ " Error: \n%s." % str(output)
|
|
+ "The cmd is %s " % setCronCmd)
|
|
|
|
g_logger.log("Successfully Set CRON.")
|
|
|
|
def __cancelCron(self):
|
|
"""
|
|
function: clean kerberos_monitor process and delete cron
|
|
input : NA
|
|
output: NA
|
|
"""
|
|
g_logger.log("Deleting kerberos monitor.")
|
|
try:
|
|
# Remove cron
|
|
crontabFile = "%s/gauss_crontab_file_%d" % \
|
|
(EnvUtil.getTmpDirFromEnv(g_opts.user),
|
|
os.getpid())
|
|
cmd = "crontab -l > %s; " % crontabFile
|
|
cmd += "sed -i '/^.*kinit.*$/d' '%s'; " % crontabFile
|
|
cmd += "crontab '%s';" % crontabFile
|
|
cmd += "rm -f '%s'" % crontabFile
|
|
|
|
(status, output) = subprocess.getstatusoutput(cmd)
|
|
if (status != 0):
|
|
#no need raise error here, user can do it manually.
|
|
g_logger.debug("Failed to delete regular tasks. Error: \n%s"
|
|
" You can do it manually." % str(output))
|
|
g_logger.debug("The cmd is %s " % cmd)
|
|
cmd = "source '%s';export LD_LIBRARY_PATH=%s/lib:" \
|
|
"$LD_LIBRARY_PATH;export KRB5_CONFIG=" \
|
|
"$MPPDB_KRB5_FILE_PATH;%s/bin/kdestroy" % \
|
|
(g_opts.mpprcFile, g_opts.krbHomePath, g_opts.krbHomePath)
|
|
(status, output) = CmdUtil.retryGetstatusoutput(cmd)
|
|
if (status != 0):
|
|
g_logger.debug("Failed to delete ticket. Error: \n%s" %
|
|
str(output))
|
|
g_logger.debug("The cmd is %s " % cmd)
|
|
except Exception as e:
|
|
raise Exception(str(e))
|
|
g_logger.log("Successfully deleted kerberos OMMonitor.")
|
|
|
|
def __copyConf(self, src_dir, dest_dir, file_list):
|
|
for config_file in file_list:
|
|
src_path = os.path.realpath(os.path.join(src_dir, config_file))
|
|
if (not os.path.isfile(src_path)):
|
|
raise Exception(ErrorCode.GAUSS_502["GAUSS_50201"] % src_path)
|
|
dest_path = os.path.realpath(os.path.join(dest_dir, config_file))
|
|
try:
|
|
shutil.copy(src_path, dest_path)
|
|
except Exception as e:
|
|
raise Exception(ErrorCode.GAUSS_502["GAUSS_50214"] % src_path)
|
|
g_logger.log("Copy server config files successfully.")
|
|
|
|
def __initKadm5Conf(self, dest_dir):
|
|
kadm5_file = os.path.realpath(os.path.join(dest_dir, "kadm5.acl"))
|
|
cmd = "sed -i 's/#realms#/OPENGAUSS.ORG/g' %s" % kadm5_file
|
|
(status, output) = subprocess.getstatusoutput(cmd)
|
|
if (status != 0):
|
|
g_logger.debug("The cmd is %s " % cmd)
|
|
raise Exception(ErrorCode.GAUSS_502["GAUSS_50205"] % kadm5_file
|
|
+ output)
|
|
g_logger.log("Initialize \"kadm5.acl\" successfully.")
|
|
|
|
def __initKrb5Conf(self, dest_dir, dest_file='krb5.conf'):
|
|
krb5_file = os.path.realpath(os.path.join(dest_dir, dest_file))
|
|
kdc_ip = g_opts.dbNodeInfo.backIps[0]
|
|
kdc_port = 21732
|
|
gausslog = EnvUtil.getEnvironmentParameterValue("GAUSSLOG", "")
|
|
if not gausslog:
|
|
raise Exception(ErrorCode.GAUSS_518["GAUSS_51802"] % "GAUSSLOG")
|
|
cmd = "sed -i 's/#kdc_ip#/%s/g' %s && \
|
|
sed -i 's/#kdc_ports#/%d/g' %s && \
|
|
sed -i 's;#krb_conf#;%s;g' %s && \
|
|
sed -i 's;#GAUSSHOME#;%s;g' %s" % \
|
|
(kdc_ip, krb5_file,
|
|
kdc_port, krb5_file,
|
|
g_opts.gausshome_kerberso, krb5_file,
|
|
gausslog, krb5_file)
|
|
(status, output) = subprocess.getstatusoutput(cmd)
|
|
if status != 0:
|
|
g_logger.debug("The cmd is %s " % cmd)
|
|
raise Exception(ErrorCode.GAUSS_502["GAUSS_50205"] % krb5_file
|
|
+ output)
|
|
|
|
kerberoslog = os.path.join(gausslog, "kerberos")
|
|
cmd = "if [ ! -d '%s' ]; then mkdir -p '%s' -m %s; fi" % (kerberoslog,
|
|
kerberoslog, DefaultValue.KEY_DIRECTORY_MODE)
|
|
(status, output) = subprocess.getstatusoutput(cmd)
|
|
if status != 0:
|
|
g_logger.debug("The cmd is %s " % cmd)
|
|
raise Exception(ErrorCode.GAUSS_502["GAUSS_50205"] % krb5_file
|
|
+ output)
|
|
|
|
g_logger.log("Initialize \"krb5.conf\" successfully.")
|
|
|
|
def __initKdcConf(self, dest_dir):
|
|
self.__initKrb5Conf(dest_dir, "kdc.conf")
|
|
|
|
kdc_file = os.path.realpath(os.path.join(dest_dir, "kdc.conf"))
|
|
cmd = "sed -i 's;#KRB_HOME#;%s;g' %s" % (g_opts.gausshome, kdc_file)
|
|
(status, output) = subprocess.getstatusoutput(cmd)
|
|
if status != 0:
|
|
g_logger.debug("The cmd is %s " % cmd)
|
|
raise Exception(ErrorCode.GAUSS_502["GAUSS_50205"] % kdc_file
|
|
+ output)
|
|
|
|
g_logger.log("Initialize \"kdc.conf\" successfully.")
|
|
|
|
def __initMppdbSite(self, dest_dir):
|
|
mppdb_site_file = os.path.realpath(os.path.join(dest_dir,
|
|
"mppdb-site.xml"))
|
|
principal = "%s/opengauss.org@OPENGAUSS.ORG " % g_opts.user
|
|
cmd = "sed -i 's;#mppdb.kerberos.principal#;%s;g' %s" % \
|
|
(principal, mppdb_site_file)
|
|
(status, output) = subprocess.getstatusoutput(cmd)
|
|
if status != 0:
|
|
g_logger.debug("The cmd is %s " % cmd)
|
|
raise Exception(ErrorCode.GAUSS_502["GAUSS_50205"] %
|
|
mppdb_site_file + output)
|
|
|
|
cmd = "sed -i 's;#KRB_HOME#;%s;g' %s" % (g_opts.gausshome,
|
|
mppdb_site_file)
|
|
(status, output) = subprocess.getstatusoutput(cmd)
|
|
if status != 0:
|
|
g_logger.debug("The cmd is %s " % cmd)
|
|
raise Exception(ErrorCode.GAUSS_502["GAUSS_50205"] %
|
|
mppdb_site_file + output)
|
|
|
|
kdc_conf = os.path.realpath(os.path.join(g_opts.gausshome_kerberso,
|
|
"kdc.conf"))
|
|
cmd = "sed -i 's;#KRB_CONFIG#;%s;g' %s" % (kdc_conf, mppdb_site_file)
|
|
(status, output) = subprocess.getstatusoutput(cmd)
|
|
if status != 0:
|
|
g_logger.debug("The cmd is %s " % cmd)
|
|
raise Exception(ErrorCode.GAUSS_502["GAUSS_50205"] %
|
|
mppdb_site_file + output)
|
|
|
|
keytab = os.path.realpath(os.path.join(g_opts.gausshome_kerberso,
|
|
"%s.keytab" % g_opts.user))
|
|
cmd = "sed -i 's;#mppdb.kerberos.keytab#;%s;g' %s" % (keytab,
|
|
mppdb_site_file)
|
|
(status, output) = subprocess.getstatusoutput(cmd)
|
|
if status != 0:
|
|
g_logger.debug("The cmd is %s " % cmd)
|
|
raise Exception(ErrorCode.GAUSS_502["GAUSS_50205"] %
|
|
mppdb_site_file + output)
|
|
|
|
g_logger.log("Initialize \"mppdb-site.xml\" successfully.")
|
|
|
|
def __configKrb5(self, isUninstall, isServer=False):
|
|
"""
|
|
function: config specify krb5.conf
|
|
input: isUninstall, isServer
|
|
output: NA
|
|
"""
|
|
destfile = "%s/krb5.conf" % os.path.dirname(g_opts.mpprcFile)
|
|
if not isUninstall:
|
|
if isServer:
|
|
# 1.copy conf files to GAUSSHOME/kerberos
|
|
CONFIG_LIST = ["kadm5.acl", "kdc.conf", "krb5.conf"]
|
|
src_path = os.path.realpath(os.path.join(g_opts.gausshome,
|
|
"etc", "kerberos"))
|
|
self.__copyConf(src_path, g_opts.gausshome_kerberso,
|
|
CONFIG_LIST)
|
|
# 2.initialize conf files
|
|
self.__initKadm5Conf(g_opts.gausshome_kerberso)
|
|
self.__initKrb5Conf(g_opts.gausshome_kerberso)
|
|
self.__initKdcConf(g_opts.gausshome_kerberso)
|
|
|
|
else:
|
|
#1. copy "krb5.conf"
|
|
if (os.path.isfile(g_opts.krbConfigPath)):
|
|
shutil.copy(g_opts.krbConfigPath, destfile)
|
|
else:
|
|
raise Exception(ErrorCode.GAUSS_502["GAUSS_50228"] %
|
|
g_opts.krbConfigPath)
|
|
#2. change cache file path of kerberos
|
|
if(not os.path.isdir("%s/auth_config" %
|
|
os.path.dirname(g_opts.mpprcFile))):
|
|
raise Exception(ErrorCode.GAUSS_502["GAUSS_50201"] %
|
|
("%s/auth_config" %
|
|
os.path.dirname(g_opts.mpprcFile)))
|
|
cmd = "sed -i '/default_realm.*/i default_ccache_name = " \
|
|
"FILE:%s/auth_config/krb5cc_%s' '%s'" % \
|
|
(os.path.dirname(g_opts.mpprcFile),
|
|
pwd.getpwnam(g_opts.user).pw_uid, destfile)
|
|
(status, output) = subprocess.getstatusoutput(cmd)
|
|
if status != 0:
|
|
g_logger.debug("The cmd is %s " % cmd)
|
|
raise Exception("Config 'krb5.conf' failed.cmd: %s" % cmd)
|
|
g_logger.log("Client Config \"krb5.conf\" successfully.")
|
|
|
|
else:
|
|
if os.path.isfile(destfile):
|
|
os.remove(destfile)
|
|
|
|
g_logger.log("Clear \"krb5.conf\" successfully.")
|
|
|
|
def __initUser(self):
|
|
|
|
# create kerberos database
|
|
kerberos_database_file = \
|
|
os.path.realpath(os.path.join(g_opts.gausshome,
|
|
"var", "krb5kdc", "principal"))
|
|
if os.path.isfile(kerberos_database_file):
|
|
g_logger.debug("kerberos database has existed.")
|
|
else:
|
|
dir_permission = 0o700
|
|
os.makedirs(os.path.dirname(kerberos_database_file),
|
|
mode=dir_permission)
|
|
passwd = RandomValue.getRandStr()
|
|
cmd = "source %s && echo -e '%s\n%s\n%s' | kdb5_util create -r OPENGAUSS.ORG -s -m" % \
|
|
(g_opts.mpprcFile, str(passwd), str(passwd), str(passwd))
|
|
proc = FastPopen(cmd, stdout=PIPE, stderr=PIPE, preexec_fn=os.setsid, close_fds=True)
|
|
stdout, stderr = proc.communicate()
|
|
output = stdout + stderr
|
|
status = proc.returncode
|
|
# clean pwd info
|
|
del passwd, cmd
|
|
gc.collect()
|
|
if status != 0:
|
|
g_logger.debug("The cmd is kdb5_util")
|
|
raise Exception(ErrorCode.GAUSS_514["GAUSS_51400"] %
|
|
"kdb5_util")
|
|
g_logger.debug("Create kerberos database successfully.")
|
|
|
|
# create kerberos database user
|
|
cmd = "source %s && kadmin.local -q \"addprinc " \
|
|
"-randkey %s/opengauss.org\"" % \
|
|
(g_opts.mpprcFile, g_opts.user)
|
|
proc = FastPopen(cmd, stdout=PIPE, stderr=PIPE, preexec_fn=os.setsid, close_fds=True)
|
|
stdout, stderr = proc.communicate()
|
|
output = stdout + stderr
|
|
status = proc.returncode
|
|
if status != 0:
|
|
raise Exception(ErrorCode.GAUSS_514["GAUSS_51400"] % cmd + output)
|
|
g_logger.debug("Create kerberos database user successfully.")
|
|
|
|
# create kerberos keytab
|
|
cmd = "source %s && kadmin.local -q \"ktadd -k %s/%s.keytab " \
|
|
"%s/opengauss.org@OPENGAUSS.ORG\"" % \
|
|
(g_opts.mpprcFile, g_opts.gausshome_kerberso,
|
|
g_opts.user, g_opts.user)
|
|
proc = FastPopen(cmd, stdout=PIPE, stderr=PIPE, preexec_fn=os.setsid, close_fds=True)
|
|
stdout, stderr = proc.communicate()
|
|
output = stdout + stderr
|
|
status = proc.returncode
|
|
if status != 0:
|
|
raise Exception(ErrorCode.GAUSS_514["GAUSS_51400"] % cmd + output)
|
|
g_logger.debug("Create kerberos keytab successfully.")
|
|
|
|
g_logger.log("Initialize kerberos user successfully.")
|
|
|
|
def __startServer(self):
|
|
# start kdc
|
|
cmd = "source %s && krb5kdc" % g_opts.mpprcFile
|
|
(status, output) = subprocess.getstatusoutput(cmd)
|
|
if status != 0:
|
|
raise Exception(ErrorCode.GAUSS_514["GAUSS_51400"] % cmd + output)
|
|
g_logger.debug("Start kerberos kdc successfully.")
|
|
|
|
g_logger.log("Start kerberos server successfully.")
|
|
|
|
def __distributeKeyAndSite(self):
|
|
hostlist = []
|
|
for hostName in g_sshTool.hostNames:
|
|
if hostName != g_opts.dbNodeInfo.name:
|
|
hostlist.append(hostName)
|
|
g_logger.debug("Distribute nodes: %s" % ",".join(hostlist))
|
|
# distribute keytab
|
|
dest_kerberos_dir = os.path.dirname(g_opts.gausshome_kerberso) + '/'
|
|
g_sshTool.scpFiles(g_opts.gausshome_kerberso,
|
|
dest_kerberos_dir, hostlist)
|
|
|
|
# create auth_config
|
|
mppdb_site_dir = os.path.join(os.path.dirname(g_opts.mpprcFile),
|
|
"auth_config")
|
|
cmd = "if [ ! -d '%s' ]; then mkdir %s; fi" % (mppdb_site_dir,
|
|
mppdb_site_dir)
|
|
g_sshTool.executeCommand(cmd, DefaultValue.SUCCESS, g_sshTool.hostNames,
|
|
g_opts.mpprcFile)
|
|
# copy mppdb-site.xml
|
|
src_path = os.path.realpath(os.path.join(g_opts.gausshome, "etc",
|
|
"kerberos", "mppdb-site.xml"))
|
|
if not os.path.isfile(src_path):
|
|
raise Exception(ErrorCode.GAUSS_502["GAUSS_50201"] % src_path)
|
|
dest_path = os.path.realpath(os.path.join(mppdb_site_dir,
|
|
"mppdb-site.xml"))
|
|
try:
|
|
shutil.copy(src_path, dest_path)
|
|
except Exception as e:
|
|
raise Exception(ErrorCode.GAUSS_502["GAUSS_50214"] % src_path)
|
|
# init mppdb-site.xml
|
|
self.__initMppdbSite(mppdb_site_dir)
|
|
# distribute mppdb-site.xml
|
|
g_sshTool.scpFiles(dest_path, dest_path, hostlist)
|
|
|
|
def __restartOMmonitor(self):
|
|
"""
|
|
function: restart OM_monitor for new environment variable
|
|
input: NA
|
|
output: NA
|
|
"""
|
|
#1. find om_monitor process
|
|
DefaultValue.KillAllProcess(g_opts.user, "om_monitor")
|
|
g_logger.log("Kill om_monitor successfully.")
|
|
cmd = "source /etc/profile;source '%s';%s/bin/om_monitor " \
|
|
"-L %s/%s/cm/om_monitor >> /dev/null 2>&1 &" % \
|
|
(g_opts.mpprcFile, g_clusterInfo.appPath,
|
|
g_clusterInfo.logPath, g_opts.user)
|
|
(status, output) = subprocess.getstatusoutput(cmd)
|
|
if status != 0:
|
|
g_logger.debug("The cmd is %s " % cmd)
|
|
g_logger.debug("Start om_monitor process failed.")
|
|
g_logger.debug("Error:%s\n" % output)
|
|
|
|
g_logger.log("Restart om_monitor succeed.")
|
|
|
|
def __cleanAuthConfig(self):
|
|
auth_config = os.path.join(os.path.dirname(g_opts.mpprcFile),
|
|
"auth_config")
|
|
if os.path.isdir(auth_config):
|
|
try:
|
|
shutil.rmtree(auth_config)
|
|
except Exception as e:
|
|
raise Exception(ErrorCode.GAUSS_502["GAUSS_50207"] %
|
|
auth_config)
|
|
logPath = ClusterDir.getUserLogDirWithUser(g_opts.user)
|
|
kerberosLog = "%s/kerberos" % logPath
|
|
if os.path.exists(kerberosLog):
|
|
FileUtil.removeDirectory(kerberosLog)
|
|
g_logger.log("Clean auth config directory succeed.")
|
|
|
|
def __cleanServer(self):
|
|
if os.path.isdir(g_opts.gausshome_kerberso):
|
|
try:
|
|
shutil.rmtree(g_opts.gausshome_kerberso)
|
|
except Exception as e:
|
|
raise Exception(ErrorCode.GAUSS_502["GAUSS_50207"] %
|
|
g_opts.gausshome_kerberso)
|
|
|
|
krb_data = "%s/var/krb5kdc" % g_opts.gausshome
|
|
if os.path.isdir(krb_data):
|
|
try:
|
|
shutil.rmtree(krb_data)
|
|
except Exception as e:
|
|
raise Exception(ErrorCode.GAUSS_502["GAUSS_50207"] % krb_data)
|
|
|
|
# Remove cron
|
|
crontabFile = "%s/gauss_crontab_file_%d" % \
|
|
(EnvUtil.getTmpDirFromEnv(g_opts.user), os.getpid())
|
|
cmd = "crontab -l > %s; " % crontabFile
|
|
cmd += "sed -i '/^.*krb5kdc.*$/d' '%s'; " % crontabFile
|
|
cmd += "crontab '%s';" % crontabFile
|
|
cmd += "rm -f '%s'" % crontabFile
|
|
(status, output) = subprocess.getstatusoutput(cmd)
|
|
if (status != 0):
|
|
#no need raise error here, user can do it manually.
|
|
g_logger.debug("The cmd is %s " % cmd)
|
|
g_logger.debug("Failed to delete regular tasks. Error: \n%s "
|
|
"You can do it manually." % str(output))
|
|
|
|
cmd = "source /etc/profile; source '%s' && \
|
|
proc_pid_list=`ps ux | grep -E 'krb5kdc'| \
|
|
grep -v 'grep'|awk '{print \$2}'` && \
|
|
(if [ X\"$proc_pid_list\" != X\"\" ]; \
|
|
then echo \"$proc_pid_list\" | xargs -r -n 100 kill -9 ; fi)" \
|
|
% (g_opts.mpprcFile)
|
|
(status, output) = subprocess.getstatusoutput(cmd)
|
|
if (status != 0):
|
|
raise Exception(ErrorCode.GAUSS_514["GAUSS_51400"] % cmd + output)
|
|
|
|
g_logger.log("Clean Server files and process succeed.")
|
|
|
|
def __install(self):
|
|
try:
|
|
self.__configKrb5(False, g_opts.server)
|
|
self.__setUserEnvVariable(False, g_opts.server)
|
|
self.__triggerJob(False, g_opts.server)
|
|
if not g_opts.server:
|
|
self.__configPostgresql(False)
|
|
self.__configPgHba(False)
|
|
self.__configDNPgHba(False)
|
|
self.__restartOMmonitor()
|
|
g_logger.log("Successfully start Kerberos Authentication.")
|
|
except Exception as e:
|
|
self.__rollback(g_opts.server)
|
|
raise e
|
|
finally:
|
|
pass
|
|
|
|
|
|
def __uninstall(self, isRollBack=False):
|
|
self.__configKrb5(True)
|
|
self.__setUserEnvVariable(True, False, isRollBack)
|
|
self.__triggerJob(True)
|
|
self.__configPostgresql(True)
|
|
self.__configPgHba(True)
|
|
self.__configDNPgHba(True)
|
|
if not isRollBack:
|
|
self.__cleanAuthConfig()
|
|
self.__cleanServer()
|
|
g_logger.log("Successfully close Kerberos Authentication.")
|
|
|
|
def run(self):
|
|
'''
|
|
function: call start or stop
|
|
'''
|
|
if(g_opts.action == "install"):
|
|
self.__install()
|
|
elif(g_opts.action == "uninstall"):
|
|
self.__uninstall(False)
|
|
else:
|
|
raise Exception(ErrorCode.GAUSS_500["GAUSS_50000"] % g_opts.action)
|
|
|
|
|
|
def parseCommandLine():
|
|
"""
|
|
function: Check parameter from command line
|
|
input : NA
|
|
output: NA
|
|
"""
|
|
try:
|
|
opts, args = getopt.getopt(sys.argv[1:], "m:U:",
|
|
["help", "krb-server", "krb-client"])
|
|
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]))
|
|
|
|
global g_opts
|
|
g_opts = CmdOptions()
|
|
|
|
for (key, value) in opts:
|
|
if (key == "--help"):
|
|
usage()
|
|
sys.exit(0)
|
|
elif(key == "-m"):
|
|
g_opts.action = value
|
|
elif (key == "-U"):
|
|
g_opts.user = value
|
|
elif (key == "--krb-server"):
|
|
g_opts.server = True
|
|
elif (key == "--krb-client"):
|
|
g_opts.client = True
|
|
|
|
if g_opts.action == 'install':
|
|
if not g_opts.server and not g_opts.client:
|
|
GaussLog.exitWithError(ErrorCode.GAUSS_500["GAUSS_50001"] %
|
|
"-krb-server' or '--krb-client")
|
|
if g_opts.server and g_opts.client:
|
|
GaussLog.exitWithError(ErrorCode.GAUSS_500["GAUSS_50005"] %
|
|
("-krb-server", "-krb-client"))
|
|
|
|
|
|
def usage():
|
|
'''
|
|
python3 KerberosUtility.py is a utility to config a {0} cluster.
|
|
Usage:
|
|
KerberosUtility.py -m install -U USER --krb-server
|
|
KerberosUtility.py -m install -U USER --krb-client
|
|
KerberosUtility.py -m uninstall -U USER
|
|
General options:
|
|
-m "install" will set kerberos config for {0} cluster,
|
|
"uninstall" will cancel to set kerberos config for {0} cluster.
|
|
-U Cluster User for {0} cluster
|
|
Install options:
|
|
--krb-server Execute install for server.
|
|
This parameter only work for install
|
|
--krb-client Execute install for client.
|
|
This parameter only work for install
|
|
Notes:
|
|
--krb-server and --krb-client can only chose one
|
|
'''
|
|
print(usage.__doc__)
|
|
|
|
if __name__ == '__main__':
|
|
"""
|
|
main function
|
|
"""
|
|
try:
|
|
parseCommandLine()
|
|
initGlobals()
|
|
except Exception as e:
|
|
GaussLog.exitWithError(str(e))
|
|
|
|
try:
|
|
kbs = Kerberos()
|
|
kbs.run()
|
|
sys.exit(0)
|
|
except Exception as e:
|
|
g_logger.logExit(str(e))
|