/** * Project: doris.admin.web.configer-0.1.0-SNAPSHOT File Created at 2011-5-20 $Id$ Copyright 1999-2100 Alibaba.com * Corporation Limited. All rights reserved. This software is the confidential and proprietary information of Alibaba * Company. ("Confidential Information"). You shall not disclose such Confidential Information and shall use it only in * accordance with the terms of the license agreement you entered into with Alibaba.com. */ package com.alibaba.doris.admin.web.configer.module.action; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.math.NumberUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.alibaba.citrus.turbine.Context; import com.alibaba.citrus.turbine.Navigator; import com.alibaba.doris.admin.core.AdminServiceLocator; import com.alibaba.doris.admin.dataobject.PhysicalNodeDO; import com.alibaba.doris.admin.service.AdminNodeService; import com.alibaba.doris.admin.service.common.AdminServiceException; import com.alibaba.doris.admin.service.common.node.NodesManager; import com.alibaba.doris.admin.service.expansion.processor.ExpansionMigrateProcessor; import com.alibaba.doris.admin.service.failover.processor.FailoverProcessor; import com.alibaba.doris.admin.service.failover.processor.ForeverFailoverProcessor; import com.alibaba.doris.admin.service.failover.processor.TempFailoverProcessor; import com.alibaba.doris.admin.web.configer.util.PhysicalNodeUtil; import com.alibaba.doris.admin.web.configer.util.WebConstant; import com.alibaba.doris.common.StoreNodeSequenceEnum; public class NodeManageAction { private static final Log log = LogFactory.getLog(NodeManageAction.class); ExpansionMigrateProcessor expansionMigrateProcessor = ExpansionMigrateProcessor.getInstance(); FailoverProcessor foreverFailoverProcessor = ForeverFailoverProcessor.getInstance(); FailoverProcessor tempFailoverProcessor = TempFailoverProcessor.getInstance(); NodesManager nodesManager = NodesManager.getInstance(); AdminNodeService adminNodeService = AdminServiceLocator.getAdminNodeService(); public boolean isLegalMigrate(String IP, String targetSequence) { Map<String, String> checkMap = new HashMap<String, String>(); List<PhysicalNodeDO> nodeList = adminNodeService.queryNomalPhysicalNodesByIP(IP); if (nodeList != null && nodeList.size() > 0) { checkMap.put(IP, Integer.toString(nodeList.get(0).getSerialId())); } if (Integer.parseInt(targetSequence) > 0 && Integer.parseInt(targetSequence) < 9 && checkMap.get(IP) != null && !StringUtils.equals(checkMap.get(IP), targetSequence)) { return false; } else { checkMap.put(IP, targetSequence); } return true; } /** * 编辑节点信息:ip,port,physical id,machine id * */ public void doEdit(Context context, Navigator nav, HttpServletRequest request) { String editNodeId = request.getParameter("editNodeId"); nav.redirectTo(WebConstant.NODE_EDIT_LINK).withParameter("nodeId", editNodeId); } /** * 需要保证:同一台Machine下的Node不可以分配到不同的sequence里面去 Preview */ public void doPreview(Context context, Navigator nav, HttpServletRequest request) { String[] newNodes = request.getParameterValues("newNode" ); if (newNodes == null || newNodes.length == 0) return; boolean isLegalMigrateNodes = PhysicalNodeUtil.isLegalMigrateNodes(newNodes); if (!isLegalMigrateNodes) { nav.redirectTo(WebConstant.NODE_MANAGE_LIST_LINK).withParameter("errorResult", "同一台Machine下的Node不可以分配到不同的sequence里面去,请重新选择!"); return; } StringBuilder nodes = new StringBuilder(); for (String node : newNodes) { if (StringUtils.isNotBlank(node)) { String[] item = node.split("#"); if (NumberUtils.isDigits(item[1])) { boolean isLegal = adminNodeService.checkLegalMigrateByIP( item[2], StoreNodeSequenceEnum.getTypeByValue(Integer.parseInt(item[1]))); if (isLegal) { nodes.append(node).append(","); } else { nav.redirectTo(WebConstant.NODE_MANAGE_LIST_LINK).withParameter("errorResult", "同一台Machine下的Node不可以分配到不同的sequence里面去,请重新选择!"); return; } } } } if (StringUtils.isBlank(nodes.toString())) { nav.redirectTo(WebConstant.NODE_MANAGE_LIST_LINK).withParameter("errorResult", "请选择扩容的Node!"); } else { nav.redirectTo(WebConstant.NEW_NODES_PREVIEW_LINK).withParameter( "nodes", nodes.toString().substring( 0, nodes.length() - 1)).withParameter( "isPreview", request.getParameter("isPreview")); ; } } /** * 点击扩容按钮 */ public void doAdd(Context context, Navigator nav, HttpServletRequest request) { String nodes = request.getParameter("nodes"); // 新增的节点 List<String> physicalIdList = null; Map<String, List<String>> nodeMap = new HashMap<String, List<String>>(); if (StringUtils.isNotBlank(nodes)) { for (String pairStr : nodes.split(",")) { String[] pair = pairStr.split("#"); if (nodeMap.get(pair[1]) == null || nodeMap.get(pair[1]).size() == 0) { physicalIdList = new ArrayList<String>(); physicalIdList.add(pair[0]); nodeMap.put(pair[1], physicalIdList); } else { nodeMap.get(pair[1]).add(pair[0]); } } } try { for (String sequenceStr : nodeMap.keySet()) { StoreNodeSequenceEnum storeNodeSequence = StoreNodeSequenceEnum.getTypeByValue(Integer.valueOf(sequenceStr)); // standby节点直接写数据库 if (storeNodeSequence.equals(StoreNodeSequenceEnum.STANDBY_SEQUENCE)) { List<PhysicalNodeDO> nodeList = new ArrayList<PhysicalNodeDO>(); for (String physicalId : nodeMap.get(sequenceStr)) { PhysicalNodeDO nodeDo = adminNodeService.queryPhysicalNodeByPhysicalId(physicalId); nodeDo.setSerialId(StoreNodeSequenceEnum.STANDBY_SEQUENCE.getValue()); nodeList.add(nodeDo); } adminNodeService.updatePhysicalNodeList(nodeList); } else { // 正常序列和临时序列都走扩容处理 // 判断是否本序列是否在迁移中,如果在迁移中,则不可以再有扩容行为,发生迁移的序列可能为多个 boolean isMigerating = expansionMigrateProcessor.isMigrating(storeNodeSequence); // ExpansionMigrateProcessor中增加Nomal序列和非Nomal序列的逻辑处理区分 if (!isMigerating) { expansionMigrateProcessor.migerate(nodeMap.get(sequenceStr), storeNodeSequence); //reload 任务由expansionMigrateProcessor 做。此处不需要 //nodesManager.reLoadNodes(); Thread.sleep(2000); } else { nav.redirectTo(WebConstant.NEW_NODES_PREVIEW_LINK).withParameter( "errorResult", "migratingError", "第" + sequenceStr + "序列正在扩容迁移中,请等待其迁移完毕后再对其进行扩容操作。"); return; } } } } catch (Exception e) { log.error("Error happened when migrating new nodes.", e); // XXME Exception need to be resolved nav.redirectTo(WebConstant.NEW_NODES_PREVIEW_LINK).withParameter("errorResult", e.getMessage()); return; } nav.redirectTo(WebConstant.NODE_MANAGE_LIST_LINK).withParameter("errorResult", "开始扩容迁移,请查看迁移进度(需要刷新页面获取最新进度数据)!"); } /** * Re-Migrate button */ public void doReMigrate(Context context, Navigator nav, HttpServletRequest request) { String reMigrateSequenceStr = request.getParameter("reMigrateSequence"); StoreNodeSequenceEnum reMigrateSequence = StoreNodeSequenceEnum.getTypeByValue(Integer.parseInt(reMigrateSequenceStr)); try { expansionMigrateProcessor.migerate(reMigrateSequence); //nodesManager.reLoadNodes(); nav.redirectTo(WebConstant.NODE_MANAGE_LIST_LINK).withParameter("errorResult", "开始重迁,请查看迁移进度(需要刷新页面获取最新进度数据)!"); } catch (AdminServiceException e) { log.error("Error happened when Re-Migrating new nodes of sequence " + reMigrateSequenceStr, e); nav.redirectTo(WebConstant.NODE_MANAGE_LIST_LINK).withParameter("errorResult", "重迁失败," + e.getMessage()); } } /** * 解决临时失效按钮 */ public void doReplaceTempErrorNode(Context context, Navigator nav, HttpServletRequest request) { // 需要被替换的节点 // String tempErrorNodeId = request.getParameter("errorNodeId"); String tempErrorNodePhysicalId = request.getParameter("errorNodePhysicalId"); try { tempFailoverProcessor.failResolve(tempErrorNodePhysicalId); //nodesManager.reLoadNodes(); nav.redirectTo(WebConstant.NODE_MANAGE_LIST_LINK).withParameter("errorResult", "临时失效节点开始恢复,请查看恢复进度(需要刷新获取最新进度数据)"); } catch (AdminServiceException e) { log.error("临时失效节点恢复失败", e); nav.redirectTo(WebConstant.NODE_MANAGE_LIST_LINK).withParameter("errorResult", "临时失效节点恢复失败," + e.getMessage()); } } /* * 解决永久失效按钮 */ public void doReplaceForeverErrorNode(Context context, Navigator nav, HttpServletRequest request) { // 需要被替换的节点 // String tempErrorNodeId = request.getParameter("errorNodeId"); String tempErrorNodePhysicalId = request.getParameter("errorNodePhysicalId"); try { foreverFailoverProcessor.failResolve(tempErrorNodePhysicalId); //nodesManager.reLoadNodes(); nav.redirectTo(WebConstant.NODE_MANAGE_LIST_LINK).withParameter("errorResult", "永久失效节点开始恢复,请查看恢复进度(需要刷新获取最新进度数据)"); } catch (AdminServiceException e) { log.error("永久失效节点恢复失败", e); nav.redirectTo(WebConstant.NODE_MANAGE_LIST_LINK).withParameter("errorResult", "永久失效节点恢复失败," + e.getMessage()); } } /* * 删除Node按钮 */ public void doRemoveNode(Context context, HttpServletRequest request) { String removeSequence = request.getParameter("removeSequence"); String removeNodePhysicalId = request.getParameter("removeNodePhysicalId"); if (!NumberUtils.isNumber(removeSequence)) { return; } List<StoreNodeSequenceEnum> exceptSequences = new ArrayList<StoreNodeSequenceEnum>(); exceptSequences.add(StoreNodeSequenceEnum.UNUSE_SEQUENCE); exceptSequences.add(StoreNodeSequenceEnum.STANDBY_SEQUENCE); exceptSequences.add(StoreNodeSequenceEnum.TEMP_SEQUENCE); // 如果是备用序列中的节点,直接删除; if (StoreNodeSequenceEnum.UNUSE_SEQUENCE.getValue() == Integer.parseInt(removeSequence)) { adminNodeService.deletePhysicalNode(removeNodePhysicalId); nodesManager.reLoadNodes(); context.put("errorResult", "移除成功!"); } else if (PhysicalNodeUtil.isAllNodesOk(exceptSequences)) { // 此处包含新增Node到临时序列、备用序列以及Nomal序列 PhysicalNodeDO nodeDo = adminNodeService.queryPhysicalNodeByPhysicalId(removeNodePhysicalId); nodeDo.setSerialId(StoreNodeSequenceEnum.UNUSE_SEQUENCE.getValue()); adminNodeService.updatePhysicalNode(nodeDo); nodesManager.reLoadNodes(); context.put("errorResult", "移除成功!"); } else { // nav.redirectTo(WebConstant.NODE_MANAGE_LIST_LINK).withParameter("errorResult", // "Nomal序列中有失效节点,请恢复到OK状态后再行操作。"); context.put("errorResult", "Nomal序列中有失效节点,请恢复到OK状态后再行操作。"); } } }