I1UY6Q 添加参数校验:用户,用户组,版本号一致性等

This commit is contained in:
zhang_xubo
2020-09-13 16:39:27 +08:00
parent 5d90db59ae
commit 7acbe191ec
3 changed files with 161 additions and 28 deletions

View File

@ -20,12 +20,8 @@
#############################################################################
import os
import pwd
import sys
import threading
import uuid
import subprocess
import weakref
sys.path.append(sys.path[0])
from gspylib.common.DbClusterInfo import dbClusterInfo, \
@ -61,6 +57,7 @@ class Expansion(ParallelBaseOM):
os.path.join(os.path.realpath(__file__), "../../"))
self.standbyLocalMode = False
self.envFile = DefaultValue.getEnv("MPPDB_ENV_SEPARATE_PATH")
def usage(self):
"""
@ -142,6 +139,13 @@ General options:
backIpList = clusterInfo.getClusterBackIps()
nodeNameList = clusterInfo.getClusterNodeNames()
# only support single az now.
azNames = clusterInfo.getazNames()
self.azName = "AZ1"
if len(azNames) > 0:
self.azName = azNames[0]
self.localIp = backIpList[0]
self.nodeNameList = nodeNameList
self.backIpNameMap = {}
for backip in backIpList:

View File

@ -1108,7 +1108,11 @@ class ErrorCode():
"database on node is abnormal. \n"
"node [%s], user [%s], dataNode [%s]. \n"
"You can use command \"gs_ctl query -D %s\" for more "
"detail."
"detail.",
"GAUSS_35704": "[GAUSS-35704] %s [%s] does not exist on node [%s].",
"GAUSS_35705": "[GAUSS-35705] Error, the database version is "
"inconsistent in %s: %s"
}

View File

@ -25,8 +25,12 @@ import os
import getpass
import pwd
import datetime
import weakref
from random import sample
import time
import grp
import socket
import stat
from multiprocessing import Process, Value
sys.path.append(sys.path[0] + "/../../../../")
@ -134,9 +138,10 @@ class ExpansionImpl():
for host in newHosts:
# create single deploy xml file for each standby node
xmlContent = self.__generateXml(host)
fo = open("%s" % tempXmlFile, "w")
fo.write( xmlContent )
fo.close()
with os.fdopen(os.open("%s" % tempXmlFile, os.O_WRONLY | os.O_CREAT,
stat.S_IWUSR | stat.S_IRUSR),'w') as fo:
fo.write( xmlContent )
fo.close()
# send single deploy xml file to each standby node
sshTool = SshTool(host)
retmap, output = sshTool.getSshStatusOutput("mkdir -p %s" %
@ -180,7 +185,7 @@ class ExpansionImpl():
<DEVICELIST>
<DEVICE sn="1000001">
<PARAM name="name" value="{nodeName}"/>
<PARAM name="azName" value="AZ1"/>
<PARAM name="azName" value="{azName}"/>
<PARAM name="azPriority" value="1"/>
<PARAM name="backIp1" value="{backIp}"/>
<PARAM name="sshIp1" value="{sshIp}"/>
@ -193,7 +198,7 @@ class ExpansionImpl():
</ROOT>
""".format(nodeName=nodeName,backIp=backIp,appPath=appPath,
logPath=logPath,toolPath=toolPath,corePath=corePath,
sshIp=sshIp,port=port,dataNode=dataNode)
sshIp=sshIp,port=port,dataNode=dataNode,azName=self.context.azName)
return xmlConfig
def changeUser(self):
@ -582,10 +587,11 @@ retry for %s times" % start_retry_num)
subprocess.getstatusoutput("mkdir -m a+x -p %s; touch %s; \
cat /dev/null > %s" % \
(self.tempFileDir, tempShFile, tempShFile))
fo = open("%s" % tempShFile, "w")
fo.write("#bash\n")
fo.write( command )
fo.close()
with os.fdopen(os.open("%s" % tempShFile, os.O_WRONLY | os.O_CREAT,
stat.S_IWUSR | stat.S_IRUSR),'w') as fo:
fo.write("#bash\n")
fo.write( command )
fo.close()
# send guc command bashfile to each host and execute it.
sshTool.scpFiles("%s" % tempShFile, "%s" % tempShFile, [host],
@ -619,14 +625,14 @@ retry for %s times" % start_retry_num)
remoteHostInfo = nodeDict[remoteHost]
guc_repl_template = """\
gs_guc set -D {dn} -c "replconninfo{index}=\
'localhost={localhost} localport={localport} \
localheartbeatport={localeHeartPort} \
localservice={localservice} \
remotehost={remoteNode} \
remoteport={remotePort} \
remoteheartbeatport={remoteHeartPort} \
remoteservice={remoteservice}'"
gs_guc set -D {dn} -c "replconninfo{index}=\
'localhost={localhost} localport={localport} \
localheartbeatport={localeHeartPort} \
localservice={localservice} \
remotehost={remoteNode} \
remoteport={remotePort} \
remoteheartbeatport={remoteHeartPort} \
remoteservice={remoteservice}'"
""".format(dn=localeHostInfo["dataNode"],
index=index,
localhost=localeHostInfo["sshIp"],
@ -653,8 +659,13 @@ retry for %s times" % start_retry_num)
def checkLocalModeOnStandbyHosts(self):
"""
expansion the installed standby node. check standby database.
1. if the database is normal
2. if the databases version are same before existing and new
"""
standbyHosts = self.context.newHostList
envfile = self.envFile
self.logger.log("Checking the database with locale mode.")
for host in standbyHosts:
hostName = self.context.backIpNameMap[host]
@ -665,6 +676,39 @@ retry for %s times" % start_retry_num)
GaussLog.exitWithError(ErrorCode.GAUSS_357["GAUSS_35703"] %
(hostName, self.user, dataNode, dataNode))
allHostIp = []
allHostIp.append(self.context.localIp)
versionDic = {}
for hostip in standbyHosts:
allHostIp.append(hostip)
sshTool= SshTool(allHostIp)
#get version in the nodes
getversioncmd = "gaussdb --version"
resultMap, outputCollect = sshTool.getSshStatusOutput(getversioncmd,
[], envfile)
self.cleanSshToolFile(sshTool)
versionLines = outputCollect.splitlines()
for verline in versionLines:
if verline[0:9] == '[SUCCESS]':
ipKey = verline[10:-1]
continue
else:
versionStr = "".join(verline)
preVersion = versionStr.split(' ')
versionInfo = preVersion[4]
versionDic[ipKey] = versionInfo[:-2]
for hostip in versionDic:
if hostip == self.context.localIp:
versionCompare = ""
versionCompare = versionDic[hostip]
else:
if versionDic[hostip] == versionCompare:
continue
else:
GaussLog.exitWithError(ErrorCode.GAUSS_357["GAUSS_35705"] \
%(hostip, versionDic[hostip]))
self.logger.log("Successfully checked the database with locale mode.")
def preInstall(self):
@ -686,12 +730,92 @@ standby nodes.")
"""
self.logger.debug("start to delete temporary file")
hostNames = self.context.nodeNameList
sshTool = SshTool(hostNames)
clearCmd = "source %s ; rm -rf %s" % (self.envFile, self.tempFileDir)
result, output = sshTool.getSshStatusOutput(clearCmd,
hostNames, self.envFile)
self.logger.debug(output)
def checkNodesDetail(self):
"""
"""
self.checkUserAndGroupExists()
self.checkXmlFileAccessToUser()
def checkXmlFileAccessToUser(self):
"""
Check if the xml config file has readable access to user.
"""
userInfo = pwd.getpwnam(self.user)
uid = userInfo.pw_uid
gid = userInfo.pw_gid
xmlFile = self.context.xmlFile
fstat = os.stat(xmlFile)
mode = fstat[stat.ST_MODE]
if (fstat[stat.ST_UID] == uid and (mode & stat.S_IRUSR > 0)) or \
(fstat[stat.ST_GID] == gid and (mode & stat.S_IRGRP > 0)):
pass
else:
self.logger.debug("User %s has no access right for file %s" \
% (self.user, xmlFile))
os.chown(xmlFile, uid, gid)
os.chmod(xmlFile, stat.S_IRUSR)
def checkUserAndGroupExists(self):
"""
check system user and group exists and be same
on primary and standby nodes
"""
inputUser = self.user
inputGroup = self.group
user_group_id = ""
isUserExits = False
localHost = socket.gethostname()
for user in pwd.getpwall():
if user.pw_name == self.user:
user_group_id = user.pw_gid
isUserExits = True
break
if not isUserExits:
GaussLog.exitWithError(ErrorCode.GAUSS_357["GAUSS_35704"] \
% ("User", self.user, localHost))
isGroupExits = False
group_id = ""
for group in grp.getgrall():
if group.gr_name == self.group:
group_id = group.gr_gid
isGroupExits = True
if not isGroupExits:
GaussLog.exitWithError(ErrorCode.GAUSS_357["GAUSS_35704"] \
% ("Group", self.group, localHost))
if user_group_id != group_id:
GaussLog.exitWithError("User [%s] is not in the group [%s]."\
% (self.user, self.group))
hostNames = self.context.newHostList
envfile = self.envFile
sshTool = SshTool(hostNames)
#get username in the other standy nodes
getUserNameCmd = "cat /etc/passwd | grep -w %s" % inputUser
resultMap, outputCollect = sshTool.getSshStatusOutput(getUserNameCmd,
[], envfile)
for hostKey in resultMap:
if resultMap[hostKey] == STATUS_FAIL:
self.cleanSshToolFile(sshTool)
GaussLog.exitWithError(ErrorCode.GAUSS_357["GAUSS_35704"] \
% ("User", self.user, hostKey))
#get groupname in the other standy nodes
getGroupNameCmd = "cat /etc/group | grep -w %s" % inputGroup
resultMap, outputCollect = sshTool.getSshStatusOutput(getGroupNameCmd,
[], envfile)
for hostKey in resultMap:
if resultMap[hostKey] == STATUS_FAIL:
self.cleanSshToolFile(sshTool)
GaussLog.exitWithError(ErrorCode.GAUSS_357["GAUSS_35704"] \
% ("Group", self.group, hostKey))
self.cleanSshToolFile(sshTool)
def installAndExpansion(self):
"""
install database and expansion standby node with db om user
@ -727,6 +851,7 @@ Start to establish the primary-standby relationship.")
"""
start expansion
"""
self.checkNodesDetail()
# preinstall on standby nodes with root user.
if not self.context.standbyLocalMode:
self.preInstall()