/******************************************************************************* * This file is part of OpenNMS(R). * * Copyright (C) 2008-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.collectd; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.LinkedList; import java.util.List; import java.util.Map; import org.opennms.core.utils.ParameterMap; import org.opennms.core.utils.ThreadCategory; import org.opennms.netmgt.config.collector.AttributeDefinition; import org.opennms.netmgt.config.collector.CollectionResource; import org.opennms.netmgt.config.collector.CollectionSet; import org.opennms.netmgt.config.collector.CollectionSetVisitor; import org.opennms.netmgt.snmp.AggregateTracker; import org.opennms.netmgt.snmp.Collectable; import org.opennms.netmgt.snmp.CollectionTracker; import org.opennms.netmgt.snmp.SnmpAgentConfig; import org.opennms.netmgt.snmp.SnmpResult; import org.opennms.netmgt.snmp.SnmpUtils; import org.opennms.netmgt.snmp.SnmpWalker; /** * <p>SnmpCollectionSet class.</p> * * After creation, be sure to call setCollectionTimestamp with the time the collection is taken * It is inappropriate to require it in the constructor, as instances may be created independently * and at a different time from when the data is collected. (They're not currently, but it's better not to * make assumptions) * * @author ranger * @version $Id: $ */ public class SnmpCollectionSet implements Collectable, CollectionSet { public static class RescanNeeded { boolean rescanNeeded = false; public void rescanIndicated() { rescanNeeded = true; } public boolean rescanIsNeeded() { return rescanNeeded; } } private final CollectionAgent m_agent; private final OnmsSnmpCollection m_snmpCollection; private SnmpIfCollector m_ifCollector; private IfNumberTracker m_ifNumber; private SysUpTimeTracker m_sysUpTime; private SnmpNodeCollector m_nodeCollector; private int m_status=ServiceCollector.COLLECTION_FAILED; private boolean m_ignorePersist; private Date m_timestamp; /** * <p>toString</p> * * @return a {@link java.lang.String} object. */ public String toString() { StringBuffer buffer = new StringBuffer(); buffer.append("CollectionAgent: "); buffer.append(m_agent); buffer.append("\n"); buffer.append("OnmsSnmpCollection: "); buffer.append(m_snmpCollection); buffer.append("\n"); buffer.append("SnmpIfCollector: "); buffer.append(m_ifCollector); buffer.append("\n"); buffer.append("IfNumberTracker: "); buffer.append(m_ifNumber); buffer.append("\n"); buffer.append("SysUpTimeTracker: "); buffer.append(m_sysUpTime); buffer.append("\n"); buffer.append("SnmpNodeCollector: "); buffer.append(m_nodeCollector); buffer.append("\n"); return buffer.toString(); } /** * <p>Constructor for SnmpCollectionSet.</p> * * @param agent a {@link org.opennms.netmgt.collectd.CollectionAgent} object. * @param snmpCollection a {@link org.opennms.netmgt.collectd.OnmsSnmpCollection} object. */ public SnmpCollectionSet(CollectionAgent agent, OnmsSnmpCollection snmpCollection) { m_agent = agent; m_snmpCollection = snmpCollection; } /** * <p>getIfCollector</p> * * @return a {@link org.opennms.netmgt.collectd.SnmpIfCollector} object. */ public SnmpIfCollector getIfCollector() { if (m_ifCollector == null) { m_ifCollector = createIfCollector(); } return m_ifCollector; } /** * <p>getIfNumber</p> * * @return a {@link org.opennms.netmgt.collectd.IfNumberTracker} object. */ public IfNumberTracker getIfNumber() { if (m_ifNumber == null) { m_ifNumber = createIfNumberTracker(); } return m_ifNumber; } /** * <p>getSysUpTime</p> * * @return a {@link org.opennms.netmgt.collectd.SysUpTimeTracker} object. */ public SysUpTimeTracker getSysUpTime() { if (m_sysUpTime == null) { m_sysUpTime = createSysUpTimeTracker(); } return m_sysUpTime; } /** * <p>getNodeCollector</p> * * @return a {@link org.opennms.netmgt.collectd.SnmpNodeCollector} object. */ public SnmpNodeCollector getNodeCollector() { if (m_nodeCollector == null) { m_nodeCollector = createNodeCollector(); } return m_nodeCollector; } private SnmpNodeCollector createNodeCollector() { SnmpNodeCollector nodeCollector = null; if (!getAttributeList().isEmpty()) { nodeCollector = new SnmpNodeCollector(m_agent.getInetAddress(), getAttributeList(), this); } return nodeCollector; } private IfNumberTracker createIfNumberTracker() { IfNumberTracker ifNumber = null; if (hasInterfaceDataToCollect()) { ifNumber = new IfNumberTracker(); } return ifNumber; } private SysUpTimeTracker createSysUpTimeTracker() { SysUpTimeTracker sysUpTime = null; if (hasInterfaceDataToCollect()) { sysUpTime = new SysUpTimeTracker(); } return sysUpTime; } private SnmpIfCollector createIfCollector() { SnmpIfCollector ifCollector = null; // construct the ifCollector if (hasInterfaceDataToCollect() || hasGenericIndexResourceDataToCollect()) { ifCollector = new SnmpIfCollector(m_agent.getInetAddress(), getCombinedIndexedAttributes(), this); } return ifCollector; } /** * <p>getNodeInfo</p> * * @return a {@link org.opennms.netmgt.collectd.NodeInfo} object. */ public NodeInfo getNodeInfo() { return getNodeResourceType().getNodeInfo(); } boolean hasDataToCollect() { return (getNodeResourceType().hasDataToCollect() || getIfResourceType().hasDataToCollect() || hasGenericIndexResourceDataToCollect()); } boolean hasInterfaceDataToCollect() { return getIfResourceType().hasDataToCollect(); } boolean hasGenericIndexResourceDataToCollect() { return ! getGenericIndexResourceTypes().isEmpty(); } /** * <p>getCollectionAgent</p> * * @return a {@link org.opennms.netmgt.collectd.CollectionAgent} object. */ public CollectionAgent getCollectionAgent() { return m_agent; } ThreadCategory log() { return ThreadCategory.getInstance(getClass()); } Collection<SnmpAttributeType> getAttributeList() { return m_snmpCollection.getNodeResourceType(m_agent).getAttributeTypes(); } List<SnmpAttributeType> getCombinedIndexedAttributes() { List<SnmpAttributeType> attributes = new LinkedList<SnmpAttributeType>(); attributes.addAll(getIfResourceType().getAttributeTypes()); attributes.addAll(getIfAliasResourceType().getAttributeTypes()); attributes.addAll(getGenericIndexAttributeTypes()); return attributes; } /** * <p>getGenericIndexAttributeTypes</p> * * @return a {@link java.util.Collection} object. */ protected Collection<SnmpAttributeType> getGenericIndexAttributeTypes() { Collection<SnmpAttributeType> attributeTypes = new LinkedList<SnmpAttributeType>(); Collection<ResourceType> resourceTypes = getGenericIndexResourceTypes(); for (ResourceType resourceType : resourceTypes) { attributeTypes.addAll(resourceType.getAttributeTypes()); } return attributeTypes; } private Collection<ResourceType> getGenericIndexResourceTypes() { return m_snmpCollection.getGenericIndexResourceTypes(m_agent); } /** * <p>getCollectionTracker</p> * * @return a {@link org.opennms.netmgt.snmp.CollectionTracker} object. */ public CollectionTracker getCollectionTracker() { return new AggregateTracker(SnmpAttributeType.getCollectionTrackers(getAttributeTypes())); } private Collection<SnmpAttributeType> getAttributeTypes() { return m_snmpCollection.getAttributeTypes(m_agent); } /** * <p>getResources</p> * * @return a {@link java.util.Collection} object. */ public Collection<? extends CollectionResource> getResources() { return m_snmpCollection.getResources(m_agent); } /** {@inheritDoc} */ public void visit(CollectionSetVisitor visitor) { visitor.visitCollectionSet(this); for (CollectionResource resource : getResources()) { resource.visit(visitor); } visitor.completeCollectionSet(this); } CollectionTracker getTracker() { List<Collectable> trackers = new ArrayList<Collectable>(4); if (getIfNumber() != null) { trackers.add(getIfNumber()); } if (getSysUpTime() != null) { trackers.add(getSysUpTime()); } if (getNodeCollector() != null) { trackers.add(getNodeCollector()); } if (getIfCollector() != null) { trackers.add(getIfCollector()); } return new AggregateTracker(trackers); } /** * <p>createWalker</p> * * @return a {@link org.opennms.netmgt.snmp.SnmpWalker} object. */ protected SnmpWalker createWalker() { CollectionAgent agent = getCollectionAgent(); return SnmpUtils.createWalker(getAgentConfig(), "SnmpCollectors for " + agent.getHostAddress(), getTracker()); } private void logStartedWalker() { if (log().isDebugEnabled()) { log().debug( "collect: successfully instantiated " + "SnmpNodeCollector() for " + getCollectionAgent().getHostAddress()); } } private void logFinishedWalker() { log().info( "collect: node SNMP query for address " + getCollectionAgent().getHostAddress() + " complete."); } /** * Log error and return COLLECTION_FAILED is there is a failure. * * @param walker * @throws CollectionWarning */ void verifySuccessfulWalk(SnmpWalker walker) throws CollectionException { if (!walker.failed()) { return; } if (walker.timedOut()) { throw new CollectionTimedOut(walker.getErrorMessage()); } String message = "collection failed for " + getCollectionAgent().getHostAddress() + " due to: " + walker.getErrorMessage(); // Note: getErrorThrowable() return value can be null throw new CollectionWarning(message, walker.getErrorThrowable()); } void collect() throws CollectionException { // XXX Should we have a call to hasDataToCollect here? try { // now collect the data SnmpWalker walker = createWalker(); walker.start(); logStartedWalker(); // wait for collection to finish walker.waitFor(); logFinishedWalker(); // Was the collection successful? verifySuccessfulWalk(walker); m_status = ServiceCollector.COLLECTION_SUCCEEDED; } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new CollectionWarning("collect: Collection of node SNMP " + "data for interface " + getCollectionAgent().getHostAddress() + " interrupted: " + e, e); } } boolean checkDisableForceRescan(final String disabledString) { final Map<String, Object> parameters = m_snmpCollection.getServiceParameters().getParameters(); final String src = ParameterMap.getKeyedString(parameters, "disableForceRescan", null); return ((src != null) && (src.toLowerCase().equals("all") || src.toLowerCase().equals(disabledString))); } void checkForNewInterfaces(SnmpCollectionSet.RescanNeeded rescanNeeded) { if (!hasInterfaceDataToCollect()) { return; } if (checkDisableForceRescan("ifnumber")) { log().info("checkForNewInterfaces: check rescan is disabled for node " + m_agent.getNodeId()); return; } logIfCounts(); if (getIfNumber().isChanged(getCollectionAgent().getSavedIfCount())) { log().info("Sending rescan event because the number of interfaces on primary SNMP " + "interface " + getCollectionAgent().getHostAddress() + " has changed, generating 'ForceRescan' event."); rescanNeeded.rescanIndicated(); } getCollectionAgent().setSavedIfCount(getIfNumber().getIntValue()); } void checkForSystemRestart(SnmpCollectionSet.RescanNeeded rescanNeeded) { if (!hasInterfaceDataToCollect()) { return; } if (checkDisableForceRescan("sysuptime")) { log().info("checkForSystemRestart: check rescan is disabled for node " + m_agent.getNodeId()); return; } logSysUpTime(); m_ignorePersist = false; if (getSysUpTime().isChanged(getCollectionAgent().getSavedSysUpTime())) { log().info("Sending rescan event because sysUpTime has changed on primary SNMP " + "interface " + getCollectionAgent().getHostAddress() + ", generating 'ForceRescan' event."); rescanNeeded.rescanIndicated(); /* * Only on sysUpTime change (i.e. SNMP Agent Restart) we must ignore collected data * to avoid spikes on RRD/JRB files */ m_ignorePersist = true; getCollectionAgent().setSavedSysUpTime(-1); } else { getCollectionAgent().setSavedSysUpTime(getSysUpTime().getLongValue()); } } private void logIfCounts() { if (log().isDebugEnabled()) { CollectionAgent agent = getCollectionAgent(); log().debug("collect: nodeId: " + agent.getNodeId() + " interface: " + agent.getHostAddress() + " ifCount: " + getIfNumber().getIntValue() + " savedIfCount: " + agent.getSavedIfCount()); } } private void logSysUpTime() { if (log().isDebugEnabled()) { CollectionAgent agent = getCollectionAgent(); log().debug("collect: nodeId: " + agent.getNodeId() + " interface: " + agent.getHostAddress() + " sysUpTime: " + getSysUpTime().getLongValue() + " savedSysUpTime: " + agent.getSavedSysUpTime()); } } /** * <p>rescanNeeded</p> * * @return a boolean. */ public boolean rescanNeeded() { final RescanNeeded rescanNeeded = new RescanNeeded(); visit(new ResourceVisitor() { public void visitResource(CollectionResource resource) { log().debug("rescanNeeded: Visiting resource " + resource); if (resource.rescanNeeded()) { log().debug("Sending rescan event for "+getCollectionAgent()+" because resource "+resource+" indicated it was needed"); rescanNeeded.rescanIndicated(); } } }); checkForNewInterfaces(rescanNeeded); checkForSystemRestart(rescanNeeded); return rescanNeeded.rescanIsNeeded(); } /** * <p>getAgentConfig</p> * * @return a {@link org.opennms.netmgt.snmp.SnmpAgentConfig} object. */ public SnmpAgentConfig getAgentConfig() { SnmpAgentConfig agentConfig = getCollectionAgent().getAgentConfig(); agentConfig.setPort(m_snmpCollection.getSnmpPort(agentConfig.getPort())); agentConfig.setRetries(m_snmpCollection.getSnmpRetries(agentConfig.getRetries())); agentConfig.setTimeout(m_snmpCollection.getSnmpTimeout(agentConfig.getTimeout())); agentConfig.setReadCommunity(m_snmpCollection.getSnmpReadCommunity(agentConfig.getReadCommunity())); agentConfig.setWriteCommunity(m_snmpCollection.getSnmpWriteCommunity(agentConfig.getWriteCommunity())); agentConfig.setProxyFor(m_snmpCollection.getSnmpProxyFor(agentConfig.getProxyFor())); agentConfig.setVersion(m_snmpCollection.getSnmpVersion(agentConfig.getVersion())); agentConfig.setMaxVarsPerPdu(m_snmpCollection.getSnmpMaxVarsPerPdu(agentConfig.getMaxVarsPerPdu())); agentConfig.setMaxRepetitions(m_snmpCollection.getSnmpMaxRepetitions(agentConfig.getMaxRepetitions())); agentConfig.setMaxRequestSize(m_snmpCollection.getSnmpMaxRequestSize(agentConfig.getMaxRequestSize())); agentConfig.setSecurityName(m_snmpCollection.getSnmpSecurityName(agentConfig.getSecurityName())); agentConfig.setAuthPassPhrase(m_snmpCollection.getSnmpAuthPassPhrase(agentConfig.getAuthPassPhrase())); agentConfig.setAuthProtocol(m_snmpCollection.getSnmpAuthProtocol(agentConfig.getAuthProtocol())); agentConfig.setPrivPassPhrase(m_snmpCollection.getSnmpPrivPassPhrase(agentConfig.getPrivPassPhrase())); agentConfig.setPrivProtocol(m_snmpCollection.getSnmpPrivProtocol(agentConfig.getPrivProtocol())); return agentConfig; } /** * <p>notifyIfNotFound</p> * * @param attrType a {@link org.opennms.netmgt.config.collector.AttributeDefinition} object. * @param res a {@link org.opennms.netmgt.snmp.SnmpResult} object. */ public void notifyIfNotFound(AttributeDefinition attrType, SnmpResult res) { // Don't bother sending a rescan event in this case since localhost is not going to be there anyway //triggerRescan(); log().info("Unable to locate resource for agent "+getCollectionAgent()+" with instance id "+res.getInstance()+" while collecting attribute "+attrType); } /* Not used anymore - done in CollectableService void saveAttributes(final ServiceParameters params) { BasePersister persister = createPersister(params); visit(persister); } private BasePersister createPersister(ServiceParameters params) { if (Boolean.getBoolean("org.opennms.rrd.storeByGroup")) { return new GroupPersister(params); } else { return new OneToOnePersister(params); } }*/ private NodeResourceType getNodeResourceType() { return m_snmpCollection.getNodeResourceType(getCollectionAgent()); } private IfResourceType getIfResourceType() { return m_snmpCollection.getIfResourceType(getCollectionAgent()); } private IfAliasResourceType getIfAliasResourceType() { return m_snmpCollection.getIfAliasResourceType(getCollectionAgent()); } /** * <p>getStatus</p> * * @return a int. */ public int getStatus() { return m_status; } /** * <p>ignorePersist</p> * * @return a boolean. */ public boolean ignorePersist() { return m_ignorePersist; } @Override public Date getCollectionTimestamp() { return m_timestamp; } public void setCollectionTimestamp(Date m_timestamp) { this.m_timestamp = m_timestamp; } }