# -*- 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_install is a utility to deploy a Gauss200 server. ############################################################################# import os import sys sys.path.append(sys.path[0] + "/../../") from gspylib.common.GaussLog import GaussLog from gspylib.common.Common import DefaultValue from gspylib.common.OMCommand import OMCommand from gspylib.os.gsfile import g_file from gspylib.common.DbClusterInfo import dbNodeInfo, \ dbClusterInfo, compareObject ############################################################################# # Const variables # INSTALL_STEP: the signal about install # STEPBACKUP_DIR: the backup directory storage step information # STEP_INIT: the signal about install # STEP_INSTALL: the signal about install # STEP_CONFIG: the signal about install # STEP_START: the signal about install ############################################################################# INSTALL_STEP = "" STEPBACKUP_DIR = "" STEP_INIT = "Init Install" STEP_INSTALL = "Install cluster" STEP_CONFIG = "Config cluster" STEP_START = "Start cluster" ############################################################################# # TP cluster type ############################################################################# ##################################################### # Ation type ##################################################### ACTION_INSTALL_CLUSTER = "install_cluster" ACTION_START_CLUSTER = "start_cluster" ACTION_BUILD_STANDBY = "build_standby" ACTION_BUILD_CASCADESTANDBY = "build_cascadestandby" # exit code EXEC_SUCCESS = 0 ############################################################################# # Global variables # self.context.logger: globle logger # self.context.clusterInfo: global clueter information # self.context.sshTool: globle ssh tool interface ############################################################################# class InstallImpl: """ The class is used to do perform installation """ """ init the command options save command line parameter values """ def __init__(self, install): """ function: constructor """ self.context = install def run(self): """ function: run method """ try: # check timeout time. # Notice: time_out is not supported under TP branch self.checkTimeout() # check if have done preinstall for this user on every node self.checkGaussenvFlag() # check the clueter status self.checkClusterStatus() # creating the backup directory self.prepareBackDir() # Check time consistency(only TP use it must less 2s) self.checkTimeConsistency() # install clueter self.context.logger.log("begin deploy..") self.doDeploy() self.context.logger.log("end deploy..") # close the log file self.context.logger.closeLog() except Exception as e: GaussLog.exitWithError(str(e)) def checkTimeout(self): """ function: check timeout """ pass def checkGaussenvFlag(self): """ function: check if have done preinstall for this user on every node 1 PREINSTALL_FLAG 2 INSTALL_FLAG input : NA output: NA """ try: self.context.logger.log("Check preinstall on every node.", "addStep") self.context.checkPreInstall(self.context.user, "preinstall") self.context.logger.log( "Successfully checked preinstall on every node.", "constant") except Exception as e: self.context.logger.logExit(str(e)) def checkClusterStatus(self): """ function: Check if cluster is running input : NA output: NA """ pass def checkTimeConsistency(self): """ Check time consistency between hosts in cluster :return: NA """ pass def prepareBackDir(self): """ function: Creating the backup directory input : NA output: NA """ self.context.logger.log("Creating the backup directory.", "addStep") self.context.managerOperateStepDir() # if INSTALL_STEP is exists if (os.path.exists(self.context.operateStepFile)): # read the step from INSTALL_STEP warmstep = self.context.readOperateStep() # print the step self.context.logger.log("Last time end with %s." % warmstep) self.context.logger.log("Continue this step.") # Successfully created the backup directory self.context.logger.log("Successfully created the backup directory.", "constant") def checkPgLogFileMode(self): """ function: change pg_log file mode input : NA output: NA """ pass def compareOldNewClusterConfigInfo(self, clusterInfo, oldClusterInfo): """ function: verify cluster config info between old and new cluster input : clusterInfo, oldClusterInfo output: NA """ # covert new cluster information to compare cluster compnew = self.storageDbClusterInfo(clusterInfo) # covert old cluster information to compare cluster compold = self.storageDbClusterInfo(oldClusterInfo) # do compare # if it is not same, print it. theSame, tempbuffer = compareObject(compnew, compold, "clusterInfo", []) if (theSame): self.context.logger.debug( "Static configuration matched with old " "static configuration files.") else: msg = \ "Instance[%s] are not the same." \ "\nXmlConfigFile: %s\nStaticConfigFile: %s\n" % \ (tempbuffer[0], tempbuffer[1], tempbuffer[2]) self.context.logger.log( "The cluster's static configuration " "does not match the new configuration file.") self.context.logger.log(msg.strip("\n")) return theSame def storageDbClusterInfo(self, dbclusterInfo): """ function: covert to comp cluster input : dbclusterInfo output: midClusterInfo """ # init dbcluster class midClusterInfo = dbClusterInfo() # get cluster name midClusterInfo.name = dbclusterInfo.name for dbnode in dbclusterInfo.dbNodes: compNodeInfo = dbNodeInfo() compNodeInfo.azName = dbnode.azName compNodeInfo.name = dbnode.name midClusterInfo.dbNodes.append(compNodeInfo) return midClusterInfo def doDeploy(self): """ function: Deploy Application input : NA output: NA """ # read the install setp from INSTALL_STEP self.context.logger.debug("Installing application") # compare xmlconfigInfo with staticConfigInfo gaussHome = DefaultValue.getInstallDir(self.context.user) commonStaticConfigFile = "%s/bin/cluster_static_config" % gaussHome if os.path.exists(commonStaticConfigFile): self.context.oldClusterInfo = dbClusterInfo() self.context.oldClusterInfo.initFromStaticConfig( self.context.user, commonStaticConfigFile) sameFlag = self.compareOldNewClusterConfigInfo( self.context.clusterInfo, self.context.oldClusterInfo) else: sameFlag = True step = self.context.readOperateStep() # if step is STEP_INSTALL if (step == STEP_INSTALL) or (step == STEP_CONFIG and not sameFlag): # rollback the install self.rollbackInstall() # write the install step self.context.writeOperateStep(STEP_INIT) # read the install step from INSTALL_STEP step = self.context.readOperateStep() # if step is STEP_INIT if step == STEP_INIT: # write the install step STEP_INSTALL into INSTALL_STEP self.context.writeOperateStep(STEP_INSTALL) # install Gauss200 DB self.doInstall() # write the install step STEP_CONFIG into INSTALL_STEP self.context.writeOperateStep(STEP_CONFIG) # read the install step from INSTALL_STEP step = self.context.readOperateStep() # if step is STEP_CONFIG if step == STEP_CONFIG: # config Gauss200 DB self.doConfig() # write the install step STEP_CONFIG into STEP_START self.context.writeOperateStep(STEP_START) # read the install step from INSTALL_STEP step = self.context.readOperateStep() # if step is STEP_START if step == STEP_START: # start Gauss200 DB self.doStart() # change pg_log file mode in pg_log path (only AP) self.checkPgLogFileMode() # clear the backup directory. self.context.managerOperateStepDir("delete") self.context.logger.log("Successfully installed application.") def prepareInstallCluster(self): """ prepared install cluster AP: distribute package and Check installation environment on all nodes TP: skip """ pass def installClusterApp(self): """ function: install cluster instance input : NA output: NA """ self.context.logger.log("Installing applications on all nodes.") # Installing applications cmd = "source %s;" % self.context.mpprcFile cmd += "%s -t %s -U %s -X %s -R %s -c %s -l %s %s" % ( OMCommand.getLocalScript("Local_Install"), ACTION_INSTALL_CLUSTER, self.context.user + ":" + self.context.group, self.context.xmlFile, self.context.clusterInfo.appPath, self.context.clusterInfo.name, self.context.localLog, self.getCommandOptions()) self.context.logger.debug( "Command for installing application: %s" % cmd) # exec the cmd for install application on all nodes DefaultValue.execCommandWithMode(cmd, "Install applications", self.context.sshTool, self.context.isSingle, self.context.mpprcFile) self.context.logger.log("Successfully installed APP.") def doInstall(self): """ function: do install input: NA output: NA """ self.context.logger.log("Installing the cluster.", "addStep") try: # prepared install cluster # AP: distribute package print("begin prepare Install Cluster..") self.prepareInstallCluster() except Exception as e: self.context.managerOperateStepDir("delete") self.context.logger.logExit(str(e)) try: # install cluster APP # AP: 1. check env 2. tar -xvcf PAKCAGE 3. modefy env flag self.context.logger.log("begin install Cluster..") self.installClusterApp() self.context.logger.log("begin init Instance..") self.initInstance() self.configZenithInst() self.context.logger.log("encrypt cipher and rand files " "for database.") initPasswd = self.getPasswdFromInitParam() self.context.genCipherAndRandFile(None, initPasswd) self.context.logger.log("begin to create CA cert files") self.context.createServerCa() if not self.context.localMode: self.context.createGrpcCa() except Exception as e: self.context.logger.logExit(str(e)) # Cluster installation is completed self.context.logger.log("Cluster installation is completed.", "constant") def getPasswdFromInitParam(self): """ function: get passwd from init-parameter return: passwd get passwd from --gsinit-parameter. if the passwd has been assigned, the database will install with non-interactive. """ if len(self.context.dbInitParam) == 0: return None passwd = None pwdIndex = -1 for idx,param in enumerate(self.context.dbInitParam): if param.startswith("--pwpasswd="): passwd = param[11:] pwdIndex = idx break elif param.startswith("-w="): passwd = param[3:] pwdIndex = idx break #remove initpasswd from dbInitParam. otherwise it will be printed in log. if pwdIndex > -1: self.context.dbInitParam.pop(pwdIndex) return passwd def configZenithInst(self): """ function: config zenith inst :return: """ pass def initInstance(self): """ function: init instance :return: """ pass def getCommandOptions(self): """ function: get command options """ pass def checkNodeConfig(self): """ function: Check node config on all nodes input : NA output: NA """ pass # for ap def prepareConfigCluster(self): """ function: install cluster instance input : NA output: NA """ pass def initNodeInstance(self): """ function: init instance applications input : NA output: NA """ pass def configInstance(self): """ function: config instance input : NA output: NA """ pass def distributeRackInfo(self): """ function: Distributing the rack Information File input : NA output: NA """ pass def doConfig(self): """ function: Do config action input : NA output: NA """ self.context.logger.log("Configuring.", "addStep") try: # prepared config cluster # AP: clean instance directory and check node config self.prepareConfigCluster() self.initNodeInstance() self.configInstance() self.distributeRackInfo() DefaultValue.enableWhiteList( self.context.sshTool, self.context.mpprcFile, self.context.clusterInfo.getClusterNodeNames(), self.context.logger) except Exception as e: # failed to clear the backup directory self.context.logger.logExit(str(e)) # Configuration is completed self.context.logger.log("Configuration is completed.", "constant") def startCluster(self): """ function: start cluster input : NA output: NA """ # Start cluster applications cmd = "source %s;" % self.context.mpprcFile cmd += "%s -t %s -U %s -X %s -R %s -c %s -l %s %s" % ( OMCommand.getLocalScript("Local_Install"), ACTION_START_CLUSTER, self.context.user + ":" + self.context.group, self.context.xmlFile, self.context.clusterInfo.appPath, self.context.clusterInfo.name, self.context.localLog, self.getCommandOptions()) self.context.logger.debug("Command for start cluster: %s" % cmd) DefaultValue.execCommandWithMode( cmd, "Start cluster", self.context.sshTool, self.context.isSingle or self.context.localMode, self.context.mpprcFile) # build stand by cmd = "source %s;" % self.context.mpprcFile cmd += "%s -t %s -U %s -X %s -R %s -c %s -l %s %s" % ( OMCommand.getLocalScript("Local_Install"), ACTION_BUILD_STANDBY, self.context.user + ":" + self.context.group, self.context.xmlFile, self.context.clusterInfo.appPath, self.context.clusterInfo.name, self.context.localLog, self.getCommandOptions()) self.context.logger.debug("Command for build standby: %s" % cmd) DefaultValue.execCommandWithMode( cmd, "Build standby", self.context.sshTool, self.context.isSingle or self.context.localMode, self.context.mpprcFile) # build casecadestand by cmd = "source %s;" % self.context.mpprcFile cmd += "%s -t %s -U %s -X %s -R %s -c %s -l %s %s" % ( OMCommand.getLocalScript("Local_Install"), ACTION_BUILD_CASCADESTANDBY, self.context.user + ":" + self.context.group, self.context.xmlFile, self.context.clusterInfo.appPath, self.context.clusterInfo.name, self.context.localLog, self.getCommandOptions()) self.context.logger.debug("Command for build cascade standby: %s" % cmd) for hostname in self.context.sshTool.hostNames: DefaultValue.execCommandWithMode( cmd, "Build cascade standby", self.context.sshTool, self.context.isSingle or self.context.localMode, self.context.mpprcFile, [hostname]) self.context.logger.log("Successfully started cluster.") def doStart(self): """ function:start cluster input : NA output: NA """ self.context.logger.debug("Start the cluster.", "addStep") try: tmpGucFile = "" tmpGucPath = DefaultValue.getTmpDirFromEnv(self.context.user) tmpGucFile = "%s/tmp_guc" % tmpGucPath cmd = g_file.SHELL_CMD_DICT["deleteFile"] % ( tmpGucFile, tmpGucFile) DefaultValue.execCommandWithMode(cmd, "Install applications", self.context.sshTool, self.context.isSingle, self.context.mpprcFile) # start cluster in non-native mode self.startCluster() except Exception as e: self.context.logger.logExit(str(e)) self.context.logger.debug("Successfully started the cluster.", "constant") def rollbackInstall(self): """ function: Rollback install input : NA output: NA 0 succeed 1 failed 2 rollback succeed 3 rollback failed """ pass # for olap def deleteTempFileForUninstall(self): """ function: Rollback install ,delete temporary file input : NA output: NA """ pass