/******************************************************************************* * This file is part of OpenNMS(R). * * Copyright (C) 2007-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.dao.support; import java.io.File; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.regex.Pattern; import org.opennms.core.utils.AlphaNumeric; import org.opennms.core.utils.InetAddressUtils; import org.opennms.core.utils.LazySet; import org.opennms.core.utils.SIUtils; import org.opennms.netmgt.dao.NodeDao; import org.opennms.netmgt.dao.ResourceDao; import org.opennms.netmgt.model.ExternalValueAttribute; import org.opennms.netmgt.model.OnmsAttribute; import org.opennms.netmgt.model.OnmsIpInterface; import org.opennms.netmgt.model.OnmsNode; import org.opennms.netmgt.model.OnmsResource; import org.opennms.netmgt.model.OnmsResourceType; import org.opennms.netmgt.model.OnmsSnmpInterface; import org.springframework.dao.DataAccessException; import org.springframework.orm.ObjectRetrievalFailureException; /** * FIXME Note: We should remove any graphs from the list that have external * values. See bug #1703. */ public class InterfaceSnmpResourceType implements OnmsResourceType { private ResourceDao m_resourceDao; private NodeDao m_nodeDao; /** * <p>Constructor for InterfaceSnmpResourceType.</p> * * @param resourceDao a {@link org.opennms.netmgt.dao.ResourceDao} object. * @param nodeDao a {@link org.opennms.netmgt.dao.NodeDao} object. */ public InterfaceSnmpResourceType(ResourceDao resourceDao, NodeDao nodeDao) { m_resourceDao = resourceDao; m_nodeDao = nodeDao; } /** * <p>getName</p> * * @return a {@link java.lang.String} object. */ public String getName() { return "interfaceSnmp"; } /** * <p>getLabel</p> * * @return a {@link java.lang.String} object. */ public String getLabel() { return "SNMP Interface Data"; } /** {@inheritDoc} */ public boolean isResourceTypeOnNode(int nodeId) { return isResourceTypeOnParentResource(Integer.toString(nodeId)); } private boolean isResourceTypeOnParentResource(String parentResource) { File parent = getParentResourceDirectory(parentResource, false); if (!parent.isDirectory()) { return false; } return parent.listFiles(RrdFileConstants.INTERFACE_DIRECTORY_FILTER).length > 0; } private File getParentResourceDirectory(String parentResource, boolean verify) { File snmp = new File(m_resourceDao.getRrdDirectory(verify), DefaultResourceDao.SNMP_DIRECTORY); File parent = new File(snmp, parentResource); if (verify && !parent.isDirectory()) { throw new ObjectRetrievalFailureException(File.class, "No parent resource directory exists for " + parentResource + ": " + parent); } return parent; } /** {@inheritDoc} */ public List<OnmsResource> getResourcesForNode(int nodeId) { OnmsNode node = m_nodeDao.get(nodeId); if (node == null) { throw new ObjectRetrievalFailureException(OnmsNode.class, Integer.toString(nodeId), "Could not find node with node ID " + nodeId, null); } ArrayList<OnmsResource> resources = new ArrayList<OnmsResource>(); File parent = getParentResourceDirectory(Integer.toString(nodeId), true); File[] intfDirs = parent.listFiles(RrdFileConstants.INTERFACE_DIRECTORY_FILTER); Set<OnmsSnmpInterface> snmpInterfaces = node.getSnmpInterfaces(); Map<String, OnmsSnmpInterface> intfMap = new HashMap<String, OnmsSnmpInterface>(); for (OnmsSnmpInterface snmpInterface : snmpInterfaces) { /* * 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 (snmpInterface.getIfDescr() != null) { if (Pattern.matches(".*-cef.*", snmpInterface.getIfDescr())) { continue; } } String replacedIfName = AlphaNumeric.parseAndReplace(snmpInterface.getIfName(), '_'); String replacedIfDescr = AlphaNumeric.parseAndReplace(snmpInterface.getIfDescr(), '_'); String[] keys = new String[] { replacedIfName + "-", replacedIfDescr + "-", replacedIfName + "-" + snmpInterface.getPhysAddr(), replacedIfDescr + "-" + snmpInterface.getPhysAddr() }; for (String key : keys) { if (!intfMap.containsKey(key)) { intfMap.put(key, snmpInterface); } } } for (File intfDir : intfDirs) { String name = intfDir.getName(); String desc = name; String mac = ""; // Strip off the MAC address from the end, if there is one int dashIndex = name.lastIndexOf("-"); if (dashIndex >= 0) { desc = name.substring(0, dashIndex); mac = name.substring(dashIndex + 1, name.length()); } String key = desc + "-" + mac; OnmsSnmpInterface snmpInterface = intfMap.get(key); String label; Long ifSpeed = null; String ifSpeedFriendly = null; if (snmpInterface == null) { label = name + " (*)"; } else { StringBuffer descr = new StringBuffer(); StringBuffer parenString = new StringBuffer(); if (snmpInterface.getIfAlias() != null) { parenString.append(snmpInterface.getIfAlias()); } // Append all of the IP addresses on this ifindex for (OnmsIpInterface ipif : snmpInterface.getIpInterfaces()) { String ipaddr = InetAddressUtils.str(ipif.getIpAddress()); if (!"0.0.0.0".equals(ipaddr)) { if (parenString.length() > 0) { parenString.append(", "); } parenString.append(ipaddr); } } if ((snmpInterface.getIfSpeed() != null) && (snmpInterface.getIfSpeed() != 0)) { ifSpeed = snmpInterface.getIfSpeed(); ifSpeedFriendly = SIUtils.getHumanReadableIfSpeed(ifSpeed); if (parenString.length() > 0) { parenString.append(", "); } parenString.append(ifSpeedFriendly); } if (snmpInterface.getIfName() != null) { descr.append(snmpInterface.getIfName()); } else if (snmpInterface.getIfDescr() != null) { descr.append(snmpInterface.getIfDescr()); } else { /* * Should never reach this point, since ifLabel is based on * the values of ifName and ifDescr but better safe than sorry. */ descr.append(name); } /* Add the extended information in parenthesis after the ifLabel, * if such information was found. */ if (parenString.length() > 0) { descr.append(" ("); descr.append(parenString); descr.append(")"); } label = descr.toString(); } OnmsResource resource = getResourceByNodeAndInterface(nodeId, intfDir.getName(), label, ifSpeed, ifSpeedFriendly); if (snmpInterface != null) { Set<OnmsIpInterface> ipInterfaces = snmpInterface.getIpInterfaces(); if (ipInterfaces.size() > 0) { int id = ipInterfaces.iterator().next().getId(); resource.setLink("element/interface.jsp?ipinterfaceid=" + id); } else { int ifIndex = snmpInterface.getIfIndex(); if(ifIndex > -1) { resource.setLink("element/snmpinterface.jsp?node=" + nodeId + "&ifindex=" + ifIndex); } } resource.setEntity(snmpInterface); } resources.add(resource); } return OnmsResource.sortIntoResourceList(resources); } private OnmsResource getResourceByNodeAndInterface(int nodeId, String intf, String label, Long ifSpeed, String ifSpeedFriendly) throws DataAccessException { Set<OnmsAttribute> set = new LazySet<OnmsAttribute>(new AttributeLoader(Integer.toString(nodeId), intf, ifSpeed, ifSpeedFriendly)); return new OnmsResource(intf, label, this, set); } public class AttributeLoader implements LazySet.Loader<OnmsAttribute> { private String m_parent; private String m_resource; private Long m_ifSpeed; private String m_ifSpeedFriendly; public AttributeLoader(String parent, String resource, Long ifSpeed, String ifSpeedFriendly) { m_parent = parent; m_resource = resource; m_ifSpeed = ifSpeed; m_ifSpeedFriendly = ifSpeedFriendly; } public Set<OnmsAttribute> load() { Set<OnmsAttribute> attributes = ResourceTypeUtils.getAttributesAtRelativePath(m_resourceDao.getRrdDirectory(), getRelativePathForResource(m_parent, m_resource)); if (m_ifSpeed != null) { attributes.add(new ExternalValueAttribute("ifSpeed", m_ifSpeed.toString())); } if (m_ifSpeedFriendly != null) { attributes.add(new ExternalValueAttribute("ifSpeedFriendly", m_ifSpeedFriendly)); } return attributes; } } private String getRelativePathForResource(String parent, String resource) { return DefaultResourceDao.SNMP_DIRECTORY + File.separator + parent + File.separator + resource; } /** * {@inheritDoc} * * This resource type is never available for domains. * Only the interface resource type is available for domains. */ public boolean isResourceTypeOnDomain(String domain) { return getQueryableInterfacesForDomain(domain).size() > 0; } /** {@inheritDoc} */ public List<OnmsResource> getResourcesForDomain(String domain) { ArrayList<OnmsResource> resources = new ArrayList<OnmsResource>(); List<String> ifaces = getQueryableInterfacesForDomain(domain); for (String iface : ifaces) { OnmsResource resource = getResourceByDomainAndInterface(domain, iface); try { resource.setLink("element/nodeList.htm?listInterfaces=true&snmpParm=ifAlias&snmpParmMatchType=contains&snmpParmValue=" + URLEncoder.encode(iface, "UTF-8")); } catch (UnsupportedEncodingException e) { throw new IllegalStateException("URLEncoder.encode complained about UTF-8. " + e, e); } resources.add(resource); } return OnmsResource.sortIntoResourceList(resources); } private List<String> getQueryableInterfacesForDomain(String domain) { if (domain == null) { throw new IllegalArgumentException("Cannot take null parameters."); } ArrayList<String> intfs = new ArrayList<String>(); File snmp = new File(m_resourceDao.getRrdDirectory(), DefaultResourceDao.SNMP_DIRECTORY); File domainDir = new File(snmp, domain); if (!domainDir.exists() || !domainDir.isDirectory()) { throw new IllegalArgumentException("No such directory: " + domainDir); } File[] intfDirs = domainDir.listFiles(RrdFileConstants.INTERFACE_DIRECTORY_FILTER); if (intfDirs != null && intfDirs.length > 0) { intfs.ensureCapacity(intfDirs.length); for (int i = 0; i < intfDirs.length; i++) { intfs.add(intfDirs[i].getName()); } } return intfs; } private OnmsResource getResourceByDomainAndInterface(String domain, String intf) { Set<OnmsAttribute> set = new LazySet<OnmsAttribute>(new AttributeLoader(domain, intf, null, null)); return new OnmsResource(intf, intf, this, set); } /** {@inheritDoc} */ public String getLinkForResource(OnmsResource resource) { return null; } }