/* * This file is part of DRBD Management Console by LINBIT HA-Solutions GmbH * by Rasto Levrinc. * * Copyright (C) 2009, Rastislav Levrinc * Copyright (C) 2009, LINBIT HA-Solutions GmbH. * * DRBD Management Console is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as published * by the Free Software Foundation; either version 2, or (at your option) * any later version. * * DRBD Management Console is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with drbd; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ package lcmc.crm.domain; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import lcmc.crm.service.CRM; import lcmc.common.domain.util.Tools; /** * This class holds data that were retrieved from ptest command. */ public final class PtestData { /** Pattern for LogActions. e.g. "Start res_IPaddr2_1 (hardy-a)" */ private static final Pattern PTEST_ACTIONS_PATTERN = Pattern.compile(".*LogActions:\\s+(\\S+)\\s*(?:resource)?\\s+(\\S+)\\s+\\(([^)]*)\\).*"); /** Pattern for pending actions. */ private static final Pattern PTEST_ERROR_PATTERN = Pattern.compile( "(?i).*ERROR: print_elem:\\s+\\[Action.*?: Pending \\(id: (\\S+)_(\\S+)_.*?, loc: ([^,]+).*"); /** Pattern that gets cloned resource id. */ private static final Pattern PTEST_CLONE_RESOURCE_ID_PATTERN = Pattern.compile("(.*):\\d+"); private final String toolTip; private final String shadowCib; private final Map<String, List<String>> runningOnNodes = new LinkedHashMap<String, List<String>>(); private final Map<String, List<String>> slaveOnNodes = new LinkedHashMap<String, List<String>>(); private final Map<String, List<String>> masterOnNodes = new LinkedHashMap<String, List<String>>(); private final Map<String, Boolean> managedResources = new LinkedHashMap<String, Boolean>(); public PtestData(final String raw) { if (raw == null) { toolTip = null; shadowCib = null; return; } final StringBuilder sb = new StringBuilder(300); sb.append("<html><b>"); sb.append(Tools.getString("PtestData.ToolTip")); sb.append("</b><br>"); final String[] queries = raw.split(CRM.PTEST_END_DELIM); if (queries.length != 2) { shadowCib = null; toolTip = null; return; } boolean isToolTip = false; for (final String line : queries[0].split("\\r?\\n")) { final Matcher m = PTEST_ACTIONS_PATTERN.matcher(line); final Matcher mError = PTEST_ERROR_PATTERN.matcher(line); if (m.matches()) { final String action = m.group(1); String res = m.group(2); /* Clone */ boolean clone = false; final Matcher cm = PTEST_CLONE_RESOURCE_ID_PATTERN.matcher(res); if (cm.matches()) { res = cm.group(1); clone = true; } final String state = m.group(3); List<String> nodes = runningOnNodes.get(res); if (nodes == null) { nodes = new ArrayList<String>(); } List<String> slaveNodes = null; if (clone) { slaveNodes = slaveOnNodes.get(res); if (slaveNodes == null) { slaveNodes = new ArrayList<String>(); } } List<String> masterNodes = null; if (clone) { masterNodes = masterOnNodes.get(res); if (masterNodes == null) { masterNodes = new ArrayList<String>(); } } if ("Start".equals(action)) { nodes.add(state); if (clone) { slaveNodes.add(state); } } else if ("Leave".equals(action)) { if (state.indexOf(' ') >= 0) { final String[] parts = state.split(" "); if (parts.length == 2) { final String what = parts[0]; final String node = parts[1]; if ("unmanaged".equals(node)) { managedResources.put(res, false); continue; } if ("Started".equals(what)) { nodes.add(node); } else if ("Slave".equals(what)) { nodes.add(node); if (clone) { slaveNodes.add(node); } } else if ("Master".equals(what)) { nodes.add(node); if (clone) { masterNodes.add(node); } } } } } else if ("Stop".equals(action)) { /* is handled by next regexp, if stop fails */ nodes.remove(state); if (clone) { slaveNodes.remove(state); masterNodes.remove(state); } } else if ("Move".equals(action)) { if (state.contains(" -> ")) { final String[] parts = state.split(" -> "); nodes.remove(parts[0]); nodes.add(parts[parts.length - 1]); } } else if ("Promote".equals(action)) { if (state.contains(" -> Master ")) { final String[] parts = state.split(" -> Master "); if (parts.length > 0) { nodes.add(parts[parts.length - 1]); if (clone) { slaveNodes.remove(parts[parts.length - 1]); masterNodes.add(parts[parts.length - 1]); } } } } else if ("Demote".equals(action)) { if (state.contains(" -> Slave ")) { final String[] parts = state.split(" -> Slave "); if (parts.length > 0 && clone) { masterNodes.remove(parts[parts.length - 1]); slaveNodes.add(parts[parts.length - 1]); } } } else { continue; } runningOnNodes.put(res, nodes); if (clone) { slaveOnNodes.put(res, slaveNodes); masterOnNodes.put(res, masterNodes); } if ("Leave".equals(action)) { /* don't show it in tooltip */ continue; } } else if (mError.matches()) { String res = mError.group(1); final String action = mError.group(2); final String node = mError.group(3); /* Clone */ boolean clone = false; final Matcher cm = PTEST_CLONE_RESOURCE_ID_PATTERN.matcher(res); if (cm.matches()) { res = cm.group(1); clone = true; } List<String> nodes = runningOnNodes.get(res); if (nodes == null) { nodes = new ArrayList<String>(); } List<String> slaveNodes = null; if (clone) { slaveNodes = slaveOnNodes.get(res); if (slaveNodes == null) { slaveNodes = new ArrayList<String>(); } } List<String> masterNodes = null; if (clone) { masterNodes = masterOnNodes.get(res); if (masterNodes == null) { masterNodes = new ArrayList<String>(); } } if ("stop".equals(action)) { nodes.add(node); /* stop failed */ if (clone) { slaveNodes.add(node); } } else if ("start".equals(action)) { nodes.remove(node); /* start failed */ if (clone) { slaveNodes.remove(node); masterNodes.remove(node); } } else if ("promote".equals(action)) { if (clone) { masterNodes.remove(node); /* promote failed */ slaveNodes.add(node); } } else if ("demote".equals(action) && clone) { slaveNodes.remove(node); /* demote failed */ masterNodes.add(node); } runningOnNodes.put(res, nodes); if (clone) { slaveOnNodes.put(res, slaveNodes); masterOnNodes.put(res, masterNodes); } } else { continue; } if (line.contains("_post_notify_") || line.contains("_pre_notify_") || line.contains("_monitor_")) { continue; } final String[] prefixes = {"LogActions: ", "ERROR: print_elem: "}; for (final String prefix : prefixes) { final int index = line.indexOf(prefix); if (index >= 0) { sb.append(line.substring(index + prefix.length())); sb.append("<br>"); isToolTip = true; } } } if (!isToolTip) { sb.append(Tools.getString("PtestData.NoToolTip")); } sb.append("</html>"); toolTip = sb.toString(); shadowCib = queries[1]; } public String getToolTip() { return toolTip; } String getShadowCib() { return shadowCib; } List<String> getRunningOnNodes(final String pmId) { return runningOnNodes.get(pmId); } List<String> getMasterOnNodes(final String pmId) { return masterOnNodes.get(pmId); } List<String> getSlaveOnNodes(final String pmId) { return slaveOnNodes.get(pmId); } boolean isManaged(final String pmId) { final Boolean m = managedResources.get(pmId); if (m == null) { return true; } return m; } }