# -*- 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 : drop_node_with_cm_impl.py ############################################################################# import sys import os sys.path.append(sys.path[0] + "/../../../../") from base_utils.os.net_util import NetUtil from base_utils.executor.cmd_executor import CmdExecutor from gspylib.common.ErrorCode import ErrorCode from gspylib.common.Common import DefaultValue from gspylib.component.CM.CM_OLAP.CM_OLAP import CM_OLAP from gspylib.threads.SshTool import SshTool from gspylib.os.gsfile import g_file from impl.dropnode.DropnodeImpl import DropnodeImpl class DropNodeWithCmImpl(DropnodeImpl): def __init__(self, drop_node): super(DropNodeWithCmImpl, self).__init__(drop_node) self.drop_nodes = list() self.stoped_nodes = list() self.cm_component = None self.ssh_tool = None def init_global_value(self): """ Initial global value """ self.drop_nodes = [node for node in self.context.clusterInfo.dbNodes for drop_ip in self.context.hostIpListForDel if drop_ip in node.backIps] self.ssh_tool = SshTool([node.name for node in self.context.clusterInfo.dbNodes]) self.cm_component = CM_OLAP() self.cm_component.binPath = os.path.realpath(os.path.join( self.context.clusterInfo.appPath, "bin")) local_node = [node for node in self.context.clusterInfo.dbNodes if NetUtil.GetHostIpOrName() == node.name][0] self.cm_component.instInfo = local_node.cmagents[0] self.cm_component.logger = self.logger def check_drop_cm_node(self): """ Check drop CM node prerequisites """ # 1.check node number if len(self.context.clusterInfo.dbNodes) < 3: raise Exception(ErrorCode.GAUSS_358["GAUSS_35811"]) if len(self.context.clusterInfo.dbNodes) - len(self.context.hostIpListForDel) < 2: error_msg = "The current cluster contains {0} nodes. " \ "A maximum of {1} " \ "nodes can be dropped.".format(len(self.context.clusterInfo.dbNodes), len(self.context.clusterInfo.dbNodes) - 2) raise Exception(ErrorCode.GAUSS_358["GAUSS_35811"] + error_msg) # 2.check cm_server number after drop_node all_cm_server_nodes = [node for node in self.context.clusterInfo.dbNodes if node.cmservers] drop_node_with_cm_server = [node for node in self.drop_nodes if node.cmservers] if (len(all_cm_server_nodes) - len(drop_node_with_cm_server)) < 2: raise Exception("Too many cm_server nodes are dropped.A maximum of {0} cm_server " "nodes can be dropped.".format(len(all_cm_server_nodes) - 2)) def _stop_drop_node(self): """ try to stop drop nodes """ for node in self.drop_nodes: stop_para = (node.id, "", 30, "", "") # stop node try: self.cm_component.stop_cluster(stop_para) self.stoped_nodes.append(node) except Exception as exp: self.logger.debug("Stop node failed [{0}]. Exception {1}".format(node.id, str(exp))) self.logger.log("Success stoped node [{0}].".format(node.id)) def _generate_flag_file_on_drop_nodes(self): """ Modify static file on drop nodes """ for drop_node in self.stoped_nodes: self.logger.debug("Start generate drop node flag file on drop node.") flag_file = os.path.realpath(os.path.join(self.context.clusterInfo.appPath, "bin", "drop_node_flag")) cmd = g_file.SHELL_CMD_DICT["createFile"] % (flag_file, DefaultValue.FILE_MODE, flag_file) CmdExecutor.execCommandWithMode(cmd, self.ssh_tool, host_list=[drop_node.name]) self.logger.log("Generate drop flag file on " "drop node {0} successfully.".format(drop_node.name)) def restart_new_cluster(self): """ Restart cluster """ self.logger.log("Restart cluster ...") stop_para = (0, "", 300, "", "") self.cm_component.stop_cluster(stop_para) # for flush dcc configuration DefaultValue.remove_metadata_and_dynamic_config_file(self.user, self.ssh_tool, self.logger) self.cm_component.startCluster(self.user) def run(self): """ start dropnode """ self.logger.log("Drop node with CM node is running.") self.init_global_value() self.check_drop_cm_node() self.change_user() self.logger.log("[gs_dropnode]Start to drop nodes of the cluster.") self.checkAllStandbyState() self.dropNodeOnAllHosts() self.operationOnlyOnPrimary() self._stop_drop_node() self._generate_flag_file_on_drop_nodes() self.modifyStaticConf() self.restart_new_cluster() self.logger.log("[gs_dropnode] Success to drop the target nodes.")