/******************************************************************************* * This file is part of OpenNMS(R). * * Copyright (C) 2006-2011 The OpenNMS Group, Inc. * OpenNMS(R) is Copyright (C) 1999-2011 The OpenNMS Group, Inc. * * OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc. * * OpenNMS(R) 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 3 of the License, * or (at your option) any later version. * * OpenNMS(R) 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 OpenNMS(R). If not, see: * http://www.gnu.org/licenses/ * * For more information contact: * OpenNMS(R) Licensing <license@opennms.org> * http://www.opennms.org/ * http://www.opennms.com/ *******************************************************************************/ package org.opennms.netmgt.utils; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.regex.Pattern; import org.opennms.core.resource.Vault; import org.opennms.core.utils.AlphaNumeric; import org.opennms.core.utils.ThreadCategory; /** * A convenience class for methods to encode/decode ifLabel descriptions for * storing SNMP data in an RRD file. * * @author <a href="mailto:mike@opennms.org">Mike Davidson </a> * @author <a href="mailto:larry@opennms.org">Lawrence Karnowski </a> * @author <a href="mailto:seth@opennms.org">Seth Leger </a> */ public class IfLabel extends Object { /** Constant <code>log</code> */ protected static ThreadCategory log = ThreadCategory.getInstance(IfLabel.class); /** * Return a map of useful SNMP information for the interface specified by * the nodeId and ifLabel. Essentially a "decoding" algorithm for the * ifLabel. * * @param nodeId * Node id * @param ifLabel * Interface label of format: <description>- <macAddr> * @return Map of SNMP info keyed by 'snmpInterface' table column names for * the interface specified by nodeId and ifLabel args. * @throws SQLException * if error occurs accessing the database. */ public static Map<String, String> getInterfaceInfoFromIfLabel(int nodeId, String ifLabel) { if (ifLabel == null) { throw new IllegalArgumentException("Cannot take null parameters."); } final Map<String, String> info = new HashMap<String, String>(); String desc = ifLabel; String mac = null; // first I have to strip off the MAC address from the end, if there is // one int dashIndex = ifLabel.lastIndexOf("-"); if (dashIndex >= 0) { desc = ifLabel.substring(0, dashIndex); mac = ifLabel.substring(dashIndex + 1, ifLabel.length()); } final String desc2 = desc; final String mac2 = mac; log.debug("getInterfaceInfoFromIfLabel: desc=" + desc + " mac=" + mac); String queryDesc = desc.replace('_', '%'); String query = "" + "SELECT * " + " FROM snmpinterface " + " WHERE nodeid = "+nodeId+ " AND (snmpifdescr ILIKE '"+queryDesc+"'" + " OR snmpifname ilike '"+queryDesc+"')"; log.debug("getInterfaceInfoFromLabel: query is: "+query); Querier q = new Querier(Vault.getDataSource(), query, new RowProcessor() { public void processRow(ResultSet rs) throws SQLException { // If the description portion of ifLabel matches an entry // in the snmpinterface table... /* * When Cisco Express Forwarding (CEF) or some ATM encapsulations * (AAL5) are used on Cisco routers, an additional entry might be * in the ifTable for these sub-interfaces, but there is no * performance data available for collection. This check excludes * ifTable entries where ifDescr contains "-cef". See bug #803. */ if (rs.getString("snmpifdescr") != null) { if (Pattern.matches(".*-cef.*", rs.getString("snmpifdescr"))) return; } if ((AlphaNumeric.parseAndReplace(rs.getString("snmpifname"), '_').equals(desc2)) || (AlphaNumeric.parseAndReplace(rs.getString("snmpifdescr"), '_').equals(desc2))) { // If the mac address portion of the ifLabel matches // an entry in the snmpinterface table... if (mac2 == null || mac2.equals(rs.getString("snmpphysaddr"))) { ThreadCategory.getInstance(IfLabel.class).debug("getInterfaceInfoFromIfLabel: found match..."); for (int i = 1; i <= rs.getMetaData().getColumnCount(); i++) { // Get extra information about the interface info.put(rs.getMetaData().getColumnName(i), rs.getString(i)); } } } } }); q.execute(); log.debug("getInterfaceInfoFromLabel: Querier result count is: "+q.getCount()); // The map will remain empty if the information was not located in the // DB. return Collections.unmodifiableMap(info); } /** * Get the interface labels for each interface on a given node. * * @param nodeId a int. * @return an array of {@link java.lang.String} objects. * @throws java.sql.SQLException if any. */ public static String[] getIfLabels(int nodeId) throws SQLException { String query = "" + "SELECT DISTINCT snmpifname, snmpifdescr,snmpphysaddr " + " FROM snmpinterface, ipinterface " + " WHERE (ipinterface.ismanaged!='D') " + " AND ipinterface.nodeid=snmpinterface.nodeid " + " AND ifindex = snmpifindex " + " AND ipinterface.nodeid="+nodeId; final ArrayList<String> list = new ArrayList<String>(); Querier q = new Querier(Vault.getDataSource(), query, new RowProcessor() { public void processRow(ResultSet rs) throws SQLException { String name = rs.getString("snmpifname"); String descr = rs.getString("snmpifdescr"); String physAddr = rs.getString("snmpphysaddr"); list.add(getIfLabel(name, descr, physAddr)); } }); q.execute(); String[] labels = list.toArray(new String[list.size()]); return labels; } /** * <p>getIfLabel</p> * * @param nodeId a int. * @param ipAddr a {@link java.lang.String} object. * @return a {@link java.lang.String} object. */ public static String getIfLabel(final int nodeId, final String ipAddr) { if (ipAddr == null) { throw new IllegalArgumentException("Cannot take null parameters."); } String inetAddr = org.opennms.core.utils.InetAddressUtils.normalize(ipAddr); class LabelHolder { private String m_label; public void setLabel(String label) { m_label = label; } public String getLabel() { return m_label; } } final LabelHolder holder = new LabelHolder(); String query = "" + "SELECT DISTINCT snmpifname, snmpifdescr,snmpphysaddr " + " FROM snmpinterface, ipinterface " + " WHERE (ipinterface.ismanaged!='D') " + " AND ipinterface.nodeid=snmpinterface.nodeid " + " AND ifindex=snmpifindex " + " AND ipinterface.nodeid = "+nodeId+ " AND ipinterface.ipaddr = '"+inetAddr+"'"; Querier q = new Querier(Vault.getDataSource(), query, new RowProcessor() { public void processRow(ResultSet rs) throws SQLException { String name = rs.getString("snmpifname"); String descr = rs.getString("snmpifdescr"); String physAddr = rs.getString("snmpphysaddr"); if (name != null || descr != null) { holder.setLabel(getIfLabel(name, descr, physAddr)); } else { log.warn("Interface (nodeId/ipAddr=" + nodeId + "/" + ipAddr + ") has no ifName and no ifDescr...setting to label to 'no_ifLabel'."); holder.setLabel("no_ifLabel"); } } }); q.execute(); return holder.getLabel(); } /** * <p>getIfLabelfromIfIndex</p> * * @param nodeId a int. * @param ipAddr a {@link java.lang.String} object. * @param ifIndex a int. * @return a {@link java.lang.String} object. */ public static String getIfLabelfromIfIndex(final int nodeId, final String ipAddr, final int ifIndex) { if (ipAddr == null) { throw new IllegalArgumentException("Cannot take null parameters."); } String inetAddr = org.opennms.core.utils.InetAddressUtils.normalize(ipAddr); if (ifIndex == -1) { return getIfLabel(nodeId, inetAddr); } class LabelHolder { private String m_label; public void setLabel(String label) { m_label = label; } public String getLabel() { return m_label; } } final LabelHolder holder = new LabelHolder(); String query = "" + "SELECT DISTINCT snmpifname, snmpifdescr,snmpphysaddr " + " FROM snmpinterface, ipinterface " + " WHERE (ipinterface.ismanaged!='D') " + " AND ipinterface.nodeid=snmpinterface.nodeid " + " AND ifindex=snmpifindex " + " AND ipinterface.nodeid= "+nodeId+ " AND ipinterface.ipaddr= '"+inetAddr+"'"+ " AND ipinterface.ifindex= "+ifIndex; Querier q = new Querier(Vault.getDataSource(), query, new RowProcessor() { public void processRow(ResultSet rs) throws SQLException { String name = rs.getString("snmpifname"); String descr = rs.getString("snmpifdescr"); String physAddr = rs.getString("snmpphysaddr"); if (name != null || descr != null) { holder.setLabel(getIfLabel(name, descr, physAddr)); } else { log.warn("Interface (nodeId/ipAddr=" + nodeId + "/" + ipAddr + ") has no ifName and no ifDescr...setting to label to 'no_ifLabel'."); holder.setLabel("no_ifLabel"); } } }); q.execute(); return holder.getLabel(); } /** * Return the ifLabel as a string for the given node and ifIndex. Intended for * use with non-ip interfaces. * * @return String * @param nodeId a int. * @param ifIndex a int. */ public static String getIfLabelfromSnmpIfIndex(final int nodeId, final int ifIndex) { class LabelHolder { private String m_label; public void setLabel(String label) { m_label = label; } public String getLabel() { return m_label; } } final LabelHolder holder = new LabelHolder(); String query = "" + "SELECT DISTINCT snmpifname, snmpifdescr,snmpphysaddr " + " FROM snmpinterface " + " WHERE nodeid= "+nodeId+ " AND snmpifindex= "+ifIndex; Querier q = new Querier(Vault.getDataSource(), query, new RowProcessor() { public void processRow(ResultSet rs) throws SQLException { String name = rs.getString("snmpifname"); String descr = rs.getString("snmpifdescr"); String physAddr = rs.getString("snmpphysaddr"); if (name != null || descr != null) { holder.setLabel(getIfLabel(name, descr, physAddr)); } else { log.warn("Interface (nodeId/ifIndex=" + nodeId + "/" + ifIndex + ") has no ifName and no ifDescr...setting to label to 'no_ifLabel'."); holder.setLabel("no_ifLabel"); } } }); q.execute(); return holder.getLabel(); } /** * <p>getIfLabel</p> * * @param name a {@link java.lang.String} object. * @param descr a {@link java.lang.String} object. * @param physAddr a {@link java.lang.String} object. * @return a {@link java.lang.String} object. */ public static String getIfLabel(String name, String descr, String physAddr) { // If available ifName is used to generate the label // since it is guaranteed to be unique. Otherwise // ifDescr is used. In either case, all non // alpha numeric characters are converted to // underscores to ensure that the resulting string // will make a decent file name and that RRD // won't have any problems using it // String label = null; if (name != null) { label = AlphaNumeric.parseAndReplace(name, '_'); } else if (descr != null) { label = AlphaNumeric.parseAndReplace(descr, '_'); } else { throw new IllegalArgumentException("Both name and descr are null, but at least one cannot be."); } // In order to assure the uniqueness of the // RRD file names we now append the MAC/physical // address to the end of label if it is available. // if (physAddr != null) { physAddr = AlphaNumeric.parseAndTrim(physAddr); if (physAddr.length() == 12) { label = label + "-" + physAddr; } else { if (log.isDebugEnabled()) { log.debug("initialize: physical address len is NOT 12, physAddr=" + physAddr); } } } return label; } }