# -*- 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 : OMCommand.py is utility to execute the OM command ############################################################################# import os import sys import time import subprocess from datetime import datetime, timedelta from multiprocessing.dummy import Pool as ThreadPool sys.path.append(sys.path[0] + "/../../") from gspylib.common.Common import DefaultValue, ClusterCommand, \ TempfileManagement from gspylib.common.DbClusterStatus import DbClusterStatus from gspylib.common.ErrorCode import ErrorCode from base_utils.os.env_util import EnvUtil from base_utils.os.file_util import FileUtil from base_utils.os.user_util import UserUtil from base_utils.os.cmd_util import CmdUtil class OMCommand(): """ Descript command of om """ def __init__(self): ''' Constructor ''' @staticmethod def getLocalScript(script): """ function: get local script by GPHOME input : script, path output: path """ Current_Path = os.path.dirname(os.path.realpath(__file__)) if os.getuid() != 0: gp_home = EnvUtil.getEnv("GPHOME") if gp_home: Current_Path = os.path.join(gp_home, "script/gspylib/common") LocalScript = { "Local_Backup": os.path.normpath( Current_Path + "/../../local/Backup.py"), "Local_Check_Config": os.path.normpath( Current_Path + "/../../local/CheckConfig.py"), "Local_Check_Install": os.path.normpath( Current_Path + "/../../local/CheckInstall.py"), "Local_Check_Uninstall": os.path.normpath( Current_Path + "/../../local/CheckUninstall.py"), "Local_Clean_Instance": os.path.normpath( Current_Path + "/../../local/CleanInstance.py"), "Local_Clean_OsUser": os.path.normpath( Current_Path + "/../../local/CleanOsUser.py"), "Local_Config_Hba": os.path.normpath( Current_Path + "/../../local/ConfigHba.py"), "Local_Config_CM_Res": os.path.normpath( Current_Path + "/../../local/config_cm_resource.py"), "Local_Config_Instance": os.path.normpath( Current_Path + "/../../local/ConfigInstance.py"), "Local_Init_Instance": os.path.normpath( Current_Path + "/../../local/InitInstance.py"), "Local_Install": os.path.normpath( Current_Path + "/../../local/Install.py"), "Local_Restore": os.path.normpath( Current_Path + "/../../local/Restore.py"), "Local_Uninstall": os.path.normpath( Current_Path + "/../../local/Uninstall.py"), "Local_PreInstall": os.path.normpath( Current_Path + "/../../local/PreInstallUtility.py"), "Local_Check_PreInstall": os.path.normpath( Current_Path + "/../../local/CheckPreInstall.py"), "Local_UnPreInstall": os.path.normpath( Current_Path + "/../../local/UnPreInstallUtility.py"), "Local_Roach": os.path.normpath( Current_Path + "/../../local/LocalRoach.py"), "Gauss_UnInstall": os.path.normpath( Current_Path + "/../../gs_uninstall"), "Gauss_Backup": os.path.normpath( Current_Path + "/../../gs_backup"), "Local_CheckOS": os.path.normpath( Current_Path + "/../../local/LocalCheckOS.py"), "Local_CheckSE": os.path.normpath( Current_Path + "/../../local/LocalCheckSE.py"), "Local_Check": os.path.normpath( Current_Path + "/../../local/LocalCheck.py"), "LOCAL_PERFORMANCE_CHECK": os.path.normpath( Current_Path + "/../../local/LocalPerformanceCheck.py"), "Gauss_CheckOS": os.path.normpath( Current_Path + "/../../gs_checkos"), "Gauss_CheckSE": os.path.normpath( Current_Path + "/../../gs_checkse"), "Gauss_PreInstall": os.path.normpath( Current_Path + "/../../gs_preinstall"), "Gauss_Replace": os.path.normpath( Current_Path + "/../../gs_replace"), "Gauss_Om": os.path.normpath(Current_Path + "/../../gs_om"), "UTIL_GAUSS_STAT": os.path.normpath( Current_Path + "/../../gspylib/common/GaussStat.py"), "Gauss_Check": os.path.normpath(Current_Path + "/../../gs_check"), "Local_Collect": os.path.normpath( Current_Path + "/../../local/LocalCollect.py"), "Local_Kerberos": os.path.normpath( Current_Path + "/../../local/KerberosUtility.py"), "Local_Execute_Sql": os.path.normpath( Current_Path + "/../../local/ExecuteSql.py"), "Local_StartInstance": os.path.normpath( Current_Path + "/../../local/StartInstance.py"), "Local_StopInstance": os.path.normpath( Current_Path + "/../../local/StopInstance.py"), "Local_Check_Upgrade": os.path.normpath( Current_Path + "/../../local/CheckUpgrade.py"), "Local_Check_SshAgent": os.path.normpath(Current_Path + "/../../local/CheckSshAgent.py"), "Local_Upgrade_Utility": os.path.normpath( Current_Path + "/../../local/UpgradeUtility.py"), "Local_Upgrade_CM": os.path.normpath( Current_Path + "/../../local/upgrade_cm_utility.py") } return "python3 '%s'" % LocalScript[script] @staticmethod def doCheckStaus(user, nodeId, cluster_normal_status=None, expected_redistributing=""): """ function: Check cluster status input : user, nodeId, cluster_normal_status, expected_redistributing output: status, output """ try: statusFile = "%s/gauss_check_status_%s_%d.dat" % (os.environ['HOME'], user, os.getpid()) TempfileManagement.removeTempFile(statusFile) cmd = ClusterCommand.getQueryStatusCmd("", statusFile) (status, output) = subprocess.getstatusoutput(cmd) if status != 0: TempfileManagement.removeTempFile(statusFile) return (status, output) clusterStatus = DbClusterStatus() clusterStatus.initFromFile(statusFile) TempfileManagement.removeTempFile(statusFile) except Exception as e: FileUtil.cleanTmpFile(statusFile) raise Exception( ErrorCode.GAUSS_516["GAUSS_51600"] + "Error: %s." % str(e)) status = 0 output = "" statusRep = None if nodeId > 0: nodeStatus = clusterStatus.getDbNodeStatusById(nodeId) if nodeStatus is None: raise Exception(ErrorCode.GAUSS_516["GAUSS_51619"] % nodeId) status = 0 if nodeStatus.isNodeHealthy() else 1 statusRep = nodeStatus.getNodeStatusReport() else: status = 0 if clusterStatus.isAllHealthy(cluster_normal_status) \ and (clusterStatus.redistributing == expected_redistributing or expected_redistributing == "") else 1 statusRep = clusterStatus.getClusterStatusReport() output += "cluster_state : %s\n" % clusterStatus.clusterStatus output += "redistributing : %s\n" % clusterStatus.redistributing output += "node_count : %d\n" % statusRep.nodeCount output += "Datanode State\n" output += " primary : %d\n" % statusRep.dnPrimary output += " standby : %d\n" % statusRep.dnStandby output += " secondary : %d\n" % statusRep.dnDummy output += " building : %d\n" % statusRep.dnBuild output += " abnormal : %d\n" % statusRep.dnAbnormal output += " down : %d\n" % statusRep.dnDown return (status, output) @staticmethod def getClusterStatus(isExpandScene=False): """ function: get cluster status input : user output: clusterStatus """ userAbsolutePath = UserUtil.getUserHomePath() statusFile = "%s/gauss_check_status_%d.dat" % ( userAbsolutePath, os.getpid()) TempfileManagement.removeTempFile(statusFile) cmd = ClusterCommand.getQueryStatusCmd("", statusFile) (status, output) = subprocess.getstatusoutput(cmd) if (status != 0): TempfileManagement.removeTempFile(statusFile) return None clusterStatus = DbClusterStatus() clusterStatus.initFromFile(statusFile, isExpandScene) TempfileManagement.removeTempFile(statusFile) return clusterStatus @staticmethod def wait_for_normal(logger, user, timeout=300, delta=5): status_file = os.path.join(os.path.expanduser(f"~{user}"), "gauss_check_status_%d.dat" % os.getpid()) try: logger.debug("Waiting for cluster status being satisfied.") end_time = None if timeout <= 0 else datetime.now() + timedelta( seconds=timeout) check_status = 0 while True: time.sleep(delta) if end_time is not None and datetime.now() >= end_time: check_status = 1 logger.debug("Timeout. The cluster is not available.") break # View the cluster status cmd = ClusterCommand.getQueryStatusCmd(outFile=status_file) status, output = CmdUtil.retryGetstatusoutput(cmd, retry_time=0) if status != 0: logger.debug( "Failed to obtain the cluster status. Error: \n%s" % output) continue # Determine whether the cluster status is normal or degraded cluster_status = DbClusterStatus() cluster_status.initFromFile(status_file) if cluster_status.clusterStatus == "Normal": logger.log("The cluster status is Normal.") break else: logger.debug("Cluster status is %s(%s)." % (cluster_status.clusterStatus, cluster_status.clusterStatusDetail)) if check_status != 0: raise Exception(ErrorCode.GAUSS_528["GAUSS_52800"] % (cluster_status.clusterStatus, cluster_status.clusterStatusDetail)) logger.debug("Successfully wait for cluster status become Normal.", "constant") finally: if os.path.exists(status_file): os.remove(status_file)