
(cherry picked commit from <gitee.com//opengauss/openGauss-OM/commit/ca2fd0bf6a39d3f313f23126d9ec340c3916fbb2>
717 lines
29 KiB
Python
717 lines
29 KiB
Python
#!/usr/bin/env python3
|
|
# -*- coding:utf-8 -*-
|
|
#############################################################################
|
|
# Copyright (c) 2020 Huawei Technologies Co.,Ltd.
|
|
#
|
|
# openGauss is licensed under Mulan PSL v2.
|
|
# You can use this software according to the terms
|
|
# and conditions of the Mulan PSL v2.
|
|
# You may obtain a copy of Mulan PSL v2 at:
|
|
#
|
|
# http://license.coscl.org.cn/MulanPSL2
|
|
#
|
|
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OF ANY KIND,
|
|
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
|
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
|
# See the Mulan PSL v2 for more details.
|
|
# ----------------------------------------------------------------------------
|
|
# Description : gs_preinstall is a utility to create an installation
|
|
# environment for a cluster.
|
|
#############################################################################
|
|
|
|
import os
|
|
import pwd
|
|
import sys
|
|
import grp
|
|
import subprocess
|
|
from gspylib.common.CheckPythonVersion import check_python_version, \
|
|
check_python_compiler_option, check_os_and_package_arch
|
|
|
|
package_path = os.path.dirname(os.path.realpath(__file__))
|
|
lib_path = os.path.join(package_path, "..", "lib")
|
|
clib_files = os.path.join(package_path, "gspylib/clib/*.so*")
|
|
if os.listdir(lib_path):
|
|
check_os_and_package_arch()
|
|
check_python_version()
|
|
check_python_compiler_option()
|
|
|
|
from base_utils.os.file_util import FileUtil
|
|
from gspylib.common.GaussLog import GaussLog
|
|
if "--unused-third-party" in sys.argv:
|
|
FileUtil.cleanDirectoryContent(lib_path)
|
|
FileUtil.removeFile(clib_files)
|
|
|
|
# use system pip dependecies
|
|
import psutil
|
|
import netifaces
|
|
import cryptography
|
|
import paramiko
|
|
else:
|
|
check_os_and_package_arch()
|
|
check_python_version()
|
|
check_python_compiler_option()
|
|
from gspylib.common.copy_python_lib import copy_lib
|
|
copy_lib()
|
|
|
|
from gspylib.common.Common import DefaultValue
|
|
from gspylib.common.ErrorCode import ErrorCode
|
|
from gspylib.common.ParallelBaseOM import ParallelBaseOM
|
|
from gspylib.common.ParameterParsecheck import Parameter
|
|
from gspylib.common.DbClusterInfo import dbNodeInfo, \
|
|
dbClusterInfo, compareObject
|
|
from impl.preinstall.OLAP.PreinstallImplOLAP import PreinstallImplOLAP
|
|
from gspylib.threads.SshTool import SshTool
|
|
from domain_utils.cluster_file.cluster_config_file import ClusterConfigFile
|
|
from domain_utils.cluster_file.cluster_dir import ClusterDir
|
|
from domain_utils.cluster_file.profile_file import ProfileFile
|
|
from domain_utils.cluster_file.version_info import VersionInfo
|
|
from domain_utils.cluster_os.cluster_user import ClusterUser
|
|
from base_utils.os.net_util import NetUtil
|
|
from base_utils.os.file_util import FileUtil
|
|
from domain_utils.domain_common.cluster_constants import ClusterConstants
|
|
from base_utils.os.user_util import UserUtil
|
|
from base_utils.template.xml_template import GenerateTemplate
|
|
from base_utils.os.hosts_util import HostsUtil
|
|
|
|
|
|
#############################################################################
|
|
# Global variables
|
|
#############################################################################
|
|
userNameFirtChar = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0']
|
|
|
|
|
|
class Preinstall(ParallelBaseOM):
|
|
def __init__(self):
|
|
ParallelBaseOM.__init__(self)
|
|
self.password = ""
|
|
self.envParams = []
|
|
self.rootUser = ""
|
|
self.rootPasswd = ""
|
|
self.create_user_ssh_trust = True
|
|
self.clusterToolPath = ""
|
|
self.needFixOwnerPaths = []
|
|
self.preMode = False
|
|
self.skipOSSet = False
|
|
self.skipHostnameSet = False
|
|
self.passwordsec = ""
|
|
self.corePath = ""
|
|
self.is_new_root_path = False
|
|
self.ips = ""
|
|
self.root_ssh_agent_flag = False
|
|
self.root_delete_flag = False
|
|
self.user_ssh_agent_flag = False
|
|
self.enable_dss = ""
|
|
self.dss_vg_info = ""
|
|
self.dss_vgname = ""
|
|
self.enable_perf_config = False
|
|
self.skip_cgroup_set = False
|
|
self.cluster_core_path = ""
|
|
self.om_version_cfg = None # structure like {'pkg_prefix': '', 'pgversion': '', 'commit': '', 'mode': ''}
|
|
self.og_version_cfg = None
|
|
|
|
def usage(self):
|
|
"""
|
|
gs_preinstall is a utility to create an installation environment for a cluster.
|
|
|
|
Usage:
|
|
gs_preinstall -? | --help
|
|
gs_preinstall -V | --version
|
|
gs_preinstall -U USER -G GROUP -X XMLFILE
|
|
[-L] [--skip-os-set] [--env-var="ENVVAR" [...]]
|
|
[--sep-env-file=ENVFILE] [--skip-hostname-set] [-l LOGFILE]
|
|
[--non-interactive] [--delete-root-trust] [--unused-third-party]
|
|
|
|
General options:
|
|
-U Cluster user.
|
|
-G Group of the cluster user.
|
|
-X Path of the XML configuration file.
|
|
-L Only perform preinstallation on local
|
|
nodes.
|
|
--skip-os-set Whether to skip OS parameter setting.
|
|
(The default value is set.)
|
|
--env-var="ENVVAR" OS user environment variables.
|
|
--sep-env-file=ENVFILE Path of the MPP environment file.
|
|
--skip-hostname-set Whether to skip hostname setting.
|
|
(The default value is set.)
|
|
--skip-cgroup-set Whether to skip cgroup setting.
|
|
--one-stop-install Interactive one stop installation
|
|
(The default value is unset.)
|
|
-l Path of log file.
|
|
-?, --help Show help information for this
|
|
utility, and exit the command line mode.
|
|
-V, --version Show version information.
|
|
--non-interactive Pre-execution of non-secure mode.
|
|
If it is not specified, you can choose
|
|
whether create the SSH trust for root
|
|
user or cluster user.
|
|
If it is specified, you must ensure the
|
|
SSH trust for root user and cluster
|
|
user have been created.
|
|
--delete-root-trust Whether to delete root trust.
|
|
(The default value is not deleted)
|
|
--unused-third-party Whether to use om's third-party.
|
|
(The default value is used)
|
|
--enable-perf-config Use gs_perfconfig to tune os configuration
|
|
after pre installation.
|
|
"""
|
|
print(self.usage.__doc__)
|
|
|
|
# get parameter from command
|
|
def parseCommandLine(self):
|
|
"""
|
|
function: Parse command line and save to global variable
|
|
input: NA
|
|
output: NA
|
|
"""
|
|
# init the ParaObj
|
|
ParaObj = Parameter()
|
|
ParaDict = ParaObj.ParameterCommandLine("preinstall")
|
|
# parameter -h or -?
|
|
if (ParaDict.__contains__("helpFlag")):
|
|
self.usage()
|
|
sys.exit(0)
|
|
|
|
# check whether one-stop install one-stop-install
|
|
if (ParaDict.__contains__("one_stop_install")):
|
|
xml_template = GenerateTemplate()
|
|
xml_template.run()
|
|
self.xmlFile = xml_template.target_xml
|
|
|
|
# check no root user paramters
|
|
self.check_no_root_paramter(ParaDict)
|
|
# Resolves command line arguments
|
|
# parameter -U
|
|
if (ParaDict.__contains__("user")):
|
|
self.user = ParaDict.get("user")
|
|
DefaultValue.checkPathVaild(self.user)
|
|
# parameter -G
|
|
if (ParaDict.__contains__("group")):
|
|
self.group = ParaDict.get("group")
|
|
# parameter -X
|
|
if (ParaDict.__contains__("confFile") and not ParaDict.__contains__("one_stop_install")):
|
|
self.xmlFile = ParaDict.get("confFile")
|
|
# parameter -L
|
|
if (ParaDict.__contains__("localMode")):
|
|
self.localMode = ParaDict.get("localMode")
|
|
# parameter -l
|
|
if (ParaDict.__contains__("logFile")):
|
|
self.logFile = ParaDict.get("logFile")
|
|
# parameter --env-var
|
|
if (ParaDict.__contains__("envparams")):
|
|
self.envParams = ParaDict.get("envparams")
|
|
# parameter --sep-env-file
|
|
if (ParaDict.__contains__("mpprcFile")):
|
|
self.mpprcFile = ParaDict.get("mpprcFile")
|
|
DefaultValue.checkPathVaild(self.mpprcFile)
|
|
# parameter --skip-hostname-set
|
|
if (ParaDict.__contains__("skipHostnameSet")):
|
|
self.skipHostnameSet = ParaDict.get("skipHostnameSet")
|
|
# parameter --skip-cgroup-set
|
|
if (ParaDict.__contains__("skip_cgroup_set")):
|
|
self.skip_cgroup_set = ParaDict.get("skip_cgroup_set")
|
|
# parameter --skip-os-set
|
|
if (ParaDict.__contains__("skipOSSet")):
|
|
self.skipOSSet = ParaDict.get("skipOSSet")
|
|
# parameter --non-interactive
|
|
if (ParaDict.__contains__("preMode")):
|
|
self.preMode = ParaDict.get("preMode")
|
|
# parameter --delete-root-trust
|
|
if (ParaDict.__contains__("root_delete_flag")):
|
|
self.root_delete_flag = ParaDict.get("root_delete_flag")
|
|
# parameter --enable-perf-config
|
|
if (ParaDict.__contains__("enable_perf_config")):
|
|
self.enable_perf_config = True
|
|
|
|
def check_no_root_paramter(self, para_dict):
|
|
"""
|
|
function: Check no root user paramter
|
|
input: NA
|
|
output: NA
|
|
"""
|
|
if not self.current_user_root:
|
|
if (para_dict.__contains__("user") and (para_dict.get("user") != self.user)):
|
|
GaussLog.exitWithError(ErrorCode.GAUSS_503["GAUSS_50324"])
|
|
if (para_dict.__contains__("group") and (para_dict.get("group") != self.group)):
|
|
GaussLog.exitWithError(ErrorCode.GAUSS_503["GAUSS_50324"])
|
|
if not self.skipOSSet:
|
|
GaussLog.exitWithError(ErrorCode.GAUSS_500["GAUSS_50028"] % 'os')
|
|
if not self.skip_cgroup_set:
|
|
GaussLog.exitWithError(ErrorCode.GAUSS_500["GAUSS_50028"] % 'cgroup')
|
|
|
|
def checkUserParameter(self):
|
|
"""
|
|
"""
|
|
if (self.user == ""):
|
|
GaussLog.exitWithError(
|
|
ErrorCode.GAUSS_500["GAUSS_50001"] % 'U' + ".")
|
|
elif (":" in self.user):
|
|
GaussLog.exitWithError(ErrorCode.GAUSS_500["GAUSS_50004"] % 'U')
|
|
|
|
# check if user exists
|
|
cmd = "cat /etc/passwd|grep -v nologin|grep -v halt|" \
|
|
"grep -v shutdown|awk -F: '{ print $1 }'|" \
|
|
" grep '^%s$' 2>/dev/null" % self.user
|
|
status = subprocess.getstatusoutput(cmd)[0]
|
|
if status == 0:
|
|
if pwd.getpwnam(self.user).pw_uid == 0:
|
|
# user exists and uid is 0, exit.
|
|
GaussLog.exitWithError(ErrorCode.GAUSS_503["GAUSS_50302"])
|
|
|
|
# check the local user and the localmode,
|
|
# if user not exist exit with error
|
|
if (self.localMode):
|
|
try:
|
|
DefaultValue.getUserId(self.user)
|
|
except Exception as e:
|
|
GaussLog.exitWithError(str(e))
|
|
|
|
|
|
def checkUserAndGroup(self):
|
|
"""
|
|
"""
|
|
if (self.localMode):
|
|
usergroup = grp.getgrgid(pwd.getpwnam(self.user).pw_gid).gr_name
|
|
if (self.group != usergroup):
|
|
GaussLog.exitWithError(ErrorCode.GAUSS_503["GAUSS_50305"]
|
|
+ "User:Group[%s:%s]"
|
|
% (self.user, self.group))
|
|
|
|
def check_local_node_info(self):
|
|
"""
|
|
check local node info
|
|
"""
|
|
hostName = NetUtil.GetHostIpOrName()
|
|
g_nodeInfo = self.clusterInfo.getDbNodeByName(hostName)
|
|
if (g_nodeInfo is None):
|
|
GaussLog.exitWithError(ErrorCode.GAUSS_516["GAUSS_51620"] % "local" +
|
|
" It is not a host name %s." % hostName)
|
|
|
|
def check_config_content(self, g_nodeInfo):
|
|
UserUtil.check_path_owner(ClusterConfigFile.getOneClusterConfigItem("gaussdbAppPath", self.xmlFile))
|
|
UserUtil.check_path_owner(ClusterConfigFile.getOneClusterConfigItem("gaussdbToolPath", self.xmlFile))
|
|
UserUtil.check_path_owner(ClusterConfigFile.getOneClusterConfigItem("tmpMppdbPath", self.xmlFile))
|
|
UserUtil.check_path_owner(ClusterConfigFile.getOneClusterConfigItem("gaussdbLogPath", self.xmlFile))
|
|
UserUtil.check_path_owner(ClusterConfigFile.getOneClusterConfigItem("corePath", self.xmlFile))
|
|
|
|
# check cm
|
|
UserUtil.check_path_owner(g_nodeInfo.cmDataDir)
|
|
for cmaInst in g_nodeInfo.cmagents:
|
|
UserUtil.check_path_owner(cmaInst.datadir)
|
|
for cmsInst in g_nodeInfo.cmservers:
|
|
UserUtil.check_path_owner(cmsInst.datadir)
|
|
|
|
# check dn
|
|
for dnInst in g_nodeInfo.datanodes:
|
|
UserUtil.check_path_owner(dnInst.datadir)
|
|
if (len(dnInst.ssdDir) != 0):
|
|
UserUtil.check_path_owner(dnInst.ssdDir)
|
|
# check dn xlog
|
|
for dnInst in g_nodeInfo.datanodes:
|
|
if dnInst.xlogdir != '':
|
|
UserUtil.check_path_owner(dnInst.xlogdir)
|
|
|
|
|
|
def checkEnvValueParameter(self):
|
|
"""
|
|
"""
|
|
for param in self.envParams:
|
|
# check environmental variables vaild
|
|
illegal = ["|", ";", "&", "$", ">", "<", "`", "\\", "!", "\n"]
|
|
if any(ill_char in param for ill_char in illegal):
|
|
GaussLog.exitWithError(
|
|
ErrorCode.GAUSS_500["GAUSS_50004"] % "-env-var" +
|
|
" There are illegal characters in the parameter.")
|
|
|
|
def checkLogFile(self):
|
|
"""
|
|
"""
|
|
if (self.logFile == ""):
|
|
self.logFile = self.getPreOMLogPath(
|
|
ClusterConstants.PREINSTALL_LOG_FILE, self.xmlFile)
|
|
if (not os.path.isabs(self.logFile)):
|
|
GaussLog.exitWithError(ErrorCode.GAUSS_502["GAUSS_50213"]
|
|
% self.logFile)
|
|
UserUtil.check_path_owner(self.logFile)
|
|
|
|
|
|
def checkMpprcFile(self):
|
|
"""
|
|
"""
|
|
if (self.mpprcFile == ""):
|
|
return
|
|
|
|
if (not os.path.isabs(self.mpprcFile)):
|
|
GaussLog.exitWithError(ErrorCode.GAUSS_512["GAUSS_51206"]
|
|
% self.mpprcFile)
|
|
|
|
# check mpprc file path
|
|
mpprcFilePath = os.path.normpath(self.mpprcFile)
|
|
if os.path.islink(mpprcFilePath):
|
|
GaussLog.exitWithError(ErrorCode.GAUSS_502["GAUSS_51251"] % mpprcFilePath)
|
|
if (mpprcFilePath == "/home/%s" % self.user):
|
|
GaussLog.exitWithError(ErrorCode.GAUSS_500["GAUSS_50004"] % \
|
|
'-sep-env-file' + " The file [%s] can not"
|
|
" be a reserved home "
|
|
"directory."
|
|
% self.mpprcFile)
|
|
if (os.path.isdir(self.mpprcFile)):
|
|
GaussLog.exitWithError(ErrorCode.GAUSS_500["GAUSS_50004"] % \
|
|
'-sep-env-file' + " The file [%s] can not "
|
|
"be a directory."
|
|
% self.mpprcFile)
|
|
|
|
ProfileFile.checkMpprcFileChange(self.mpprcFile, "", self.mpprcFile)
|
|
(checkstatus, checkoutput) = ProfileFile.check_env_file(self.mpprcFile)
|
|
if (not checkstatus):
|
|
if (self.mpprcFile != ""):
|
|
envfile = self.mpprcFile + " and /etc/profile"
|
|
else:
|
|
envfile = "/etc/profile and ~/.bashrc"
|
|
GaussLog.exitWithError(ErrorCode.GAUSS_518["GAUSS_51808"] % \
|
|
checkoutput + "Please check %s." % envfile)
|
|
|
|
def delete_host_ip(self):
|
|
"""
|
|
function: delete host_ip env
|
|
input: NA
|
|
output: NA
|
|
"""
|
|
if self.current_user_root:
|
|
cmd = "sed -i '/^export[ ]*HOST_IP=/d' /etc/profile"
|
|
(status, output) = subprocess.getstatusoutput(cmd)
|
|
if status != 0:
|
|
GaussLog.exitWithError(ErrorCode.GAUSS_502["GAUSS_50205"]
|
|
% ClusterConstants.ETC_PROFILE + "The cmd is %s" % cmd)
|
|
|
|
if "HOST_IP" in os.environ.keys():
|
|
os.environ.pop("HOST_IP")
|
|
|
|
def checkParameter(self):
|
|
"""
|
|
function: Check parameter from command line
|
|
input: NA
|
|
output: NA
|
|
"""
|
|
if self.current_user_root:
|
|
# check -G parameter
|
|
ClusterUser.checkGroupParameter(self.user, self.group)
|
|
|
|
# remove HOST_IP info with /etc/profile and environ
|
|
self.delete_host_ip()
|
|
# check config file
|
|
ClusterConfigFile.checkConfigFile(self.xmlFile)
|
|
# check user info
|
|
self.checkUserParameter()
|
|
# check user group match
|
|
self.checkUserAndGroup()
|
|
# init cluster info
|
|
self.initClusterInfo()
|
|
# check local node info
|
|
self.check_local_node_info()
|
|
# check env-val
|
|
self.checkEnvValueParameter()
|
|
# check mpprc file
|
|
self.checkMpprcFile()
|
|
# check log file
|
|
self.checkLogFile()
|
|
|
|
# set LD_LIBRARY_PATH add local lib
|
|
def setLibPath(self):
|
|
package_path = os.path.dirname(os.path.realpath(__file__))
|
|
ld_path = package_path + "/gspylib/clib"
|
|
rerun = True
|
|
|
|
if 'LD_LIBRARY_PATH' not in os.environ:
|
|
os.environ['LD_LIBRARY_PATH'] = ld_path
|
|
elif not os.environ.get('LD_LIBRARY_PATH').startswith(ld_path):
|
|
os.environ['LD_LIBRARY_PATH'] = \
|
|
ld_path + ":" + os.environ['LD_LIBRARY_PATH']
|
|
else:
|
|
rerun = False
|
|
|
|
if rerun:
|
|
try:
|
|
os.execve(os.path.realpath(__file__), sys.argv, os.environ)
|
|
except Exception as e:
|
|
GaussLog.exitWithError(str(e))
|
|
|
|
# decompress version.cfg from Server, and read it
|
|
def readVersioncfg(self):
|
|
def _parse_version_cfg(_cfg):
|
|
_cmd = f'cat {_cfg}'
|
|
_status, _output = subprocess.getstatusoutput(_cmd)
|
|
if _status != 0:
|
|
GaussLog.exitWithError(ErrorCode.GAUSS_502["GAUSS_50217"] %
|
|
"version.cfg" + "The cmd is %s. " % _cmd +
|
|
"The output is %s." % _output)
|
|
_lines = _output.splitlines()
|
|
_res = {
|
|
'pkg_prefix': _lines[0].replace("OM", "Server"),
|
|
'pgversion': _lines[1],
|
|
'commit': _lines[2],
|
|
'mode': 'release' if len(_lines) < 4 else _lines[3]
|
|
}
|
|
return _res
|
|
|
|
root = os.path.join(os.path.dirname(os.path.realpath(__file__)), '..')
|
|
cfg = os.path.join(root, 'version.cfg')
|
|
|
|
# read version.cfg of om package
|
|
self.om_version_cfg = _parse_version_cfg(cfg)
|
|
|
|
# upack and read version.cfg of openGauss-server package
|
|
# the existing om version.cfg will be overwritten
|
|
cmd = 'cd {} && tar -xpf {}*.tar.bz2 ./version.cfg'.format(root, self.om_version_cfg['pkg_prefix'])
|
|
status, output = subprocess.getstatusoutput(cmd)
|
|
if status != 0:
|
|
cmd = 'cd {} && tar -xpf `ls openGauss-Server*.tar.bz2 | tail -1` ./version.cfg'.format(root)
|
|
status, output = subprocess.getstatusoutput(cmd)
|
|
if status != 0:
|
|
GaussLog.exitWithError(ErrorCode.GAUSS_502["GAUSS_50217"] % "version.cfg" +
|
|
"The cmd is %s. " % cmd +
|
|
"The output is %s." % output)
|
|
self.og_version_cfg = _parse_version_cfg(cfg)
|
|
|
|
def unpackSomeToolsNeeded(self):
|
|
pkg_prefix = self.om_version_cfg['pkg_prefix']
|
|
|
|
# target tools
|
|
bin_files = ['./bin/encrypt']
|
|
dss_files = []
|
|
cm_files = []
|
|
memcheck_files = []
|
|
if self.clusterInfo.enable_dss == 'on':
|
|
cm_files = ['bin/cm_persist']
|
|
dss_files = ['./bin/perctrl', './bin/dsscmd', './lib/libdssapi.so', './bin/dss_clear.sh']
|
|
if self.og_version_cfg['mode'] == 'memcheck':
|
|
memcheck_files = ['./lib/libasan.so', './lib/libasan.so.6', './lib/libasan.so.6.0.0']
|
|
|
|
# target path
|
|
root = os.path.join(os.path.dirname(os.path.realpath(__file__)), '..')
|
|
clib = os.path.join(root, "script/gspylib/clib")
|
|
clib_dss = os.path.realpath(os.path.join(f'{clib}', f"dss_app_{self.og_version_cfg['commit']}"))
|
|
memcheck_root_lib = ''
|
|
if self.clusterInfo.enable_dss == 'on' and \
|
|
self.og_version_cfg['mode'] == 'memcheck' and \
|
|
not os.access('/usr/lib64/libasan.so.6', os.F_OK):
|
|
memcheck_root_lib = '/usr/lib64'
|
|
|
|
# unpack and move tools into target path
|
|
cmd = 'cd {} && '.format(root)
|
|
cmd += 'tar -xpf {}*.tar.bz2 {} && '.format(pkg_prefix, ' '.join(bin_files + dss_files + memcheck_files))
|
|
if cm_files:
|
|
cmd += 'tar -xpf {}*.tar.gz {} && '.format(pkg_prefix.replace("Server", "CM"), ' '.join(cm_files))
|
|
cmd += 'mkdir -p {0} -m u=rwx && '.format(clib_dss)
|
|
cmd += 'mv {} {} && '.format(' '.join(cm_files + dss_files), clib_dss)
|
|
if memcheck_root_lib != '':
|
|
cmd += 'cp ./lib/libasan.so.6 {} &&'.format(memcheck_root_lib)
|
|
cmd += '\mv {} {} && '.format(' '.join(bin_files + memcheck_files), clib)
|
|
cmd += 'cd {} && rm -rf bin'.format(root)
|
|
status, output = subprocess.getstatusoutput(cmd)
|
|
if status != 0:
|
|
GaussLog.exitWithError(ErrorCode.GAUSS_502["GAUSS_50217"] %
|
|
"version.cfg" + "The cmd is %s. " % cmd +
|
|
"The output is %s." % output)
|
|
|
|
# init global variables
|
|
def initGlobals(self):
|
|
"""
|
|
function: init global parameters
|
|
input: NA
|
|
output: NA
|
|
"""
|
|
# init the log file
|
|
self.initLogger("gs_preinstall")
|
|
|
|
|
|
current_path = os.path.dirname(os.path.realpath(__file__))
|
|
package_dir = os.path.normpath(os.path.join(current_path, "../"))
|
|
self.write_host_file(package_dir)
|
|
|
|
# get the clusterToolPath
|
|
self.clusterToolPath = ClusterDir.getPreClusterToolPath(self.xmlFile)
|
|
temp_nodes = ClusterConfigFile.getOneClusterConfigItem("nodeNames", self.xmlFile)
|
|
if len(temp_nodes.split(',')) < 2:
|
|
self.isSingle = True
|
|
os.environ[ClusterConstants.TOOL_PATH_ENV] = self.clusterToolPath
|
|
self.cluster_core_path = self.clusterInfo.readClustercorePath(self.xmlFile)
|
|
|
|
self.logger.log("Parsing the configuration file.", "addStep")
|
|
|
|
try:
|
|
# parse the configuration file
|
|
self.sshTool = SshTool(self.clusterInfo.getClusterNodeNames(),
|
|
self.logFile,
|
|
DefaultValue.TIMEOUT_PSSH_PREINSTALL)
|
|
|
|
except Exception as e:
|
|
self.logger.logExit(str(e))
|
|
|
|
# check the local hostname
|
|
if NetUtil.GetHostIpOrName() not in \
|
|
self.clusterInfo.getClusterNodeNames():
|
|
self.logger.logExit(ErrorCode.GAUSS_516["GAUSS_51619"]
|
|
% NetUtil.GetHostIpOrName())
|
|
self.logger.log("Successfully parsed the configuration file.",
|
|
"constant")
|
|
|
|
def write_host_file(self, package_dir):
|
|
hosts_file = os.path.normpath(os.path.join(package_dir, "hosts"))
|
|
if os.path.exists(hosts_file):
|
|
FileUtil.removeFile(hosts_file)
|
|
FileUtil.createFile(hosts_file)
|
|
|
|
# hosts contents
|
|
contents = {}
|
|
hostname_list = self.clusterInfo.getClusterNodeNames()
|
|
for hostname in hostname_list:
|
|
node = self.clusterInfo.getDbNodeByName(hostname)
|
|
ip = node.sshIps[0]
|
|
contents[ip] = hostname
|
|
|
|
HostsUtil.write_hosts_file(hosts_file, contents)
|
|
FileUtil.changeMode(DefaultValue.FILE_MODE, hosts_file)
|
|
|
|
# check expect for cm/create trust
|
|
def check_expect(self):
|
|
"""
|
|
function: check expect
|
|
input: NA
|
|
output: NA
|
|
"""
|
|
temp_nodes = ClusterConfigFile.getOneClusterConfigItem("nodeNames", self.xmlFile)
|
|
if len(temp_nodes.split(',')) > 1:
|
|
cmd = "echo exit|expect"
|
|
(status, _) = subprocess.getstatusoutput(cmd)
|
|
if status != 0:
|
|
GaussLog.exitWithError(ErrorCode.GAUSS_514["GAUSS_51405"] % "expect")
|
|
|
|
def getPreOMLogPath(self, logName, xml):
|
|
"""
|
|
function: get the OM log path
|
|
input: logName, xml
|
|
output: fullLogPath
|
|
"""
|
|
try:
|
|
fullLogPath = ""
|
|
# get the log path
|
|
configedLogPath = ClusterConfigFile.getOneClusterConfigItem("gaussdbLogPath",
|
|
xml)
|
|
DefaultValue.checkPathVaild(configedLogPath)
|
|
# check gaussdbLogPath is not null
|
|
if configedLogPath == "":
|
|
fullLogPath = "%s/%s/om/%s" % (
|
|
ClusterConstants.GAUSSDB_DIR, self.user, logName)
|
|
else:
|
|
fullLogPath = "%s/%s/om/%s" % (
|
|
os.path.normpath(configedLogPath), self.user, logName)
|
|
UserUtil.check_path_owner(fullLogPath)
|
|
return fullLogPath
|
|
except Exception as e:
|
|
GaussLog.exitWithError(str(e))
|
|
|
|
|
|
|
|
def change_lib_path(self):
|
|
"""
|
|
if gs_preinstall current path is /root/gauss_om/username,
|
|
so change its lib path
|
|
:return:
|
|
"""
|
|
gsom_path = os.path.realpath(
|
|
os.path.join(os.path.realpath(__file__), "../../../"))
|
|
package_path = os.path.dirname(os.path.realpath(__file__))
|
|
lib_path = os.path.join(package_path, "..", "lib")
|
|
sys.path.insert(0, lib_path)
|
|
if gsom_path == DefaultValue.ROOT_SCRIPTS_PATH:
|
|
self.is_new_root_path = True
|
|
|
|
def checkIfNest(self):
|
|
"""
|
|
function: check syncNode
|
|
"""
|
|
clusterInfo = dbClusterInfo()
|
|
clusterInfo.initFromXml(self.xmlFile)
|
|
dbNodes = clusterInfo.dbNodes
|
|
# get the dss_home path
|
|
dss_home_path = clusterInfo.dss_home
|
|
|
|
for dbinfo in dbNodes:
|
|
if dbinfo is None:
|
|
break
|
|
datanodes = dbinfo.datanodes
|
|
|
|
# check if subdir_path starts with parentdir_path
|
|
for datainfo in datanodes:
|
|
parentdir_path = os.path.normpath(datainfo.datadir)
|
|
subdir_path = os.path.normpath(dss_home_path)
|
|
if not parentdir_path.endswith(os.path.sep):
|
|
parentdir_path += os.path.sep
|
|
if not subdir_path.endswith(os.path.sep):
|
|
subdir_path += os.path.sep
|
|
|
|
if subdir_path.startswith(parentdir_path):
|
|
GaussLog.exitWithError(ErrorCode.GAUSS_502["GAUSS_50240"] % dss_home_path)
|
|
|
|
def clear_hist_time_format(self):
|
|
if self.current_user_root:
|
|
cmd = "sed -i '/HISTTIMEFORMAT=/d' /etc/profile"
|
|
(status, output) = subprocess.getstatusoutput(cmd)
|
|
if status != 0:
|
|
GaussLog.exitWithError("Clear HISTTIMEFORMAT from /etc/profile "
|
|
"failed.\nError: %s\nThe cmd is: %s\n" %
|
|
(output,cmd))
|
|
def check_current_user(self):
|
|
user_info = UserUtil.getUserInfo()
|
|
if user_info.get("uid") == 0:
|
|
self.current_user_root = True
|
|
else:
|
|
self.current_user_root = False
|
|
self.user = user_info.get("name")
|
|
self.group = user_info.get("g_name")
|
|
self.skipOSSet = True
|
|
self.skip_cgroup_set = True
|
|
|
|
def remove_mpp_env():
|
|
mpprc = os.environ.get('MPPDB_ENV_SEPARATE_PATH')
|
|
if mpprc:
|
|
os.environ.pop('MPPDB_ENV_SEPARATE_PATH')
|
|
|
|
if __name__ == '__main__':
|
|
"""
|
|
main function
|
|
"""
|
|
try:
|
|
# if not remove mpprc env, it will affect preinstall init
|
|
remove_mpp_env()
|
|
# Objectize class
|
|
preinstall = Preinstall()
|
|
# check if user is root
|
|
preinstall.check_current_user()
|
|
# remove HISTTIMEFORMAT with /etc/profile for root
|
|
preinstall.clear_hist_time_format()
|
|
# set LD_LIBRARY_PATH
|
|
preinstall.setLibPath()
|
|
# parse cmd lines
|
|
preinstall.parseCommandLine()
|
|
# check parameters
|
|
preinstall.checkParameter()
|
|
# check if the path between dss and datanode is nested
|
|
preinstall.checkIfNest()
|
|
# check expect
|
|
preinstall.check_expect()
|
|
# init global variables
|
|
preinstall.initGlobals()
|
|
# read version.cfg
|
|
preinstall.readVersioncfg()
|
|
# unpack some tools needed
|
|
preinstall.unpackSomeToolsNeeded()
|
|
|
|
preinstall.change_lib_path()
|
|
impl = PreinstallImplOLAP(preinstall)
|
|
# Perform the whole extand process
|
|
impl.run()
|
|
except Exception as e:
|
|
GaussLog.exitWithError(str(e))
|