/*******************************************************************************
* 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.capsd;
import static org.opennms.core.utils.InetAddressUtils.addr;
import static org.opennms.core.utils.InetAddressUtils.str;
import java.net.InetAddress;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.opennms.core.utils.ConfigFileConstants;
import org.opennms.core.utils.DBUtils;
import org.opennms.core.utils.ThreadCategory;
import org.opennms.netmgt.EventConstants;
import org.opennms.netmgt.capsd.IfCollector.SupportedProtocol;
import org.opennms.netmgt.capsd.snmp.IfTable;
import org.opennms.netmgt.capsd.snmp.IfTableEntry;
import org.opennms.netmgt.capsd.snmp.IfXTableEntry;
import org.opennms.netmgt.capsd.snmp.IpAddrTable;
import org.opennms.netmgt.capsd.snmp.SystemGroup;
import org.opennms.netmgt.config.CapsdConfig;
import org.opennms.netmgt.config.CapsdConfigFactory;
import org.opennms.netmgt.config.CollectdConfigFactory;
import org.opennms.netmgt.config.DataSourceFactory;
import org.opennms.netmgt.config.PollerConfig;
import org.opennms.netmgt.config.PollerConfigFactory;
import org.opennms.netmgt.eventd.EventIpcManagerFactory;
import org.opennms.netmgt.model.events.EventBuilder;
import org.opennms.netmgt.xml.event.Event;
/**
* This class is designed to rescan all the managed interfaces for a specified
* node, update the database based on the information collected, and generate
* events necessary to notify the other OpenNMS services. The constructor takes
* an integer which is the node identifier of the node to be rescanned. .
*
* @author <a href="mailto:brozow@opennms.org">Matt Brozowski</a>
* @author <a href="mailto:jamesz@opennms.org">James Zuo </a>
* @author <a href="mailto:mike@opennms.org">Mike Davidson </a>
* @author <a href="mailto:weave@oculan.com">Brian Weaver </a>
* @author <a href="http://www.opennms.org/">OpenNMS </a>
*/
public final class RescanProcessor implements Runnable {
private static final InetAddress ZERO_ZERO_ZERO_ZERO = addr("0.0.0.0");
/**
* SQL statement for retrieving the 'nodetype' field of the node table for
* the specified nodeid. Used to determine if the node is active ('A') or
* been marked as deleted ('D').
*/
final static String SQL_DB_RETRIEVE_NODE_TYPE = "SELECT nodetype FROM node WHERE nodeID=?";
/**
* SQL statement used to retrieve other nodeIds that have the same
* ipinterface as the updating node.
*/
final static String SQL_DB_RETRIEVE_OTHER_NODES = "SELECT ipinterface.nodeid FROM ipinterface, node WHERE ipinterface.ismanaged != 'D' AND ipinterface.ipaddr = ? AND ipinterface.nodeid = node.nodeid AND node.foreignsource IS NULL AND ipinterface.nodeid !=? ";
/**
* SQL statements used to reparent an interface and its associated services
* under a new parent nodeid
*/
final static String SQL_DB_REPARENT_IP_INTERFACE_LOOKUP = "SELECT ipaddr, ifindex FROM ipinterface " + "WHERE nodeID=? AND ipaddr=? AND isManaged!='D'";
final static String SQL_DB_REPARENT_IP_INTERFACE_DELETE = "DELETE FROM ipinterface " + "WHERE nodeID=? AND ipaddr=?";
final static String SQL_DB_REPARENT_IP_INTERFACE = "UPDATE ipinterface SET nodeID=? WHERE nodeID=? AND ipaddr=? AND isManaged!='D'";
final static String SQL_DB_REPARENT_SNMP_IF_LOOKUP = "SELECT id FROM snmpinterface WHERE nodeID=? AND snmpifindex=?";
final static String SQL_DB_REPARENT_SNMP_IF_DELETE = "DELETE FROM snmpinterface " + "WHERE nodeID=? AND snmpifindex=?";
final static String SQL_DB_REPARENT_SNMP_INTERFACE = "UPDATE snmpinterface SET nodeID=? WHERE nodeID=? AND snmpifindex=?";
final static String SQL_DB_REPARENT_IF_SERVICES_LOOKUP = "SELECT serviceid FROM ifservices " + "WHERE nodeID=? AND ipaddr=? AND ifindex = ? " + "AND status!='D'";
final static String SQL_DB_REPARENT_IF_SERVICES_DELETE = "DELETE FROM ifservices WHERE nodeID=? AND ipaddr=? ";
final static String SQL_DB_REPARENT_IF_SERVICES = "UPDATE ifservices SET nodeID=? WHERE nodeID=? AND ipaddr=? AND status!='D'";
/**
* SQL statements used to clear up ipinterface table, ifservices table and
* snmpinterface table when delete a duplicate node.
*/
final static String SQL_DB_DELETE_DUP_INTERFACE = "DELETE FROM ipinterface WHERE nodeID=?";
final static String SQL_DB_DELETE_DUP_SERVICES = "DELETE FROM ifservices WHERE nodeid=?";
final static String SQL_DB_DELETE_DUP_SNMPINTERFACE = "DELETE FROM snmpinterface WHERE nodeid =?";
/**
* SQL statement used to retrieve service IDs so that service name can be
* determined from ID, and map of service names
*/
private final static String SQL_RETRIEVE_SERVICE_IDS = "SELECT serviceid,servicename FROM service";
/**
* SQL statement used to update ipinterface.ismanaged
* when rescan discovers new interface
*/
private final static String SQL_DB_UPDATE_ISMANAGED = "UPDATE ipinterface SET ismanaged=? WHERE nodeID=? AND ipaddr=? AND isManaged!='D'";
/**
* Indicates if the rescan is in response to a forceRescan event.
*/
private boolean m_forceRescan;
/**
* Event list...during the rescan significant database changes cause events
* (interfaceReparented, nodeGainedService, and others) to be created and
* added to the event list. The last thing the rescan process does is send
* the events out.
*/
private final List<Event> m_eventList = new ArrayList<Event>();
/**
* Set during the rescan to true if any of the ifIndex values associated
* with a node's interface's were modified as a result of the scan.
*/
private boolean m_ifIndexOnNodeChangedFlag;
/**
* Set during the rescan to true if a new interface is added to the
* snmpInterfaces table or if any key fields of the node's snmpIntefaces
* table were modified (such as ifIndex or ifType)
*/
private boolean m_snmpIfTableChangedFlag;
private CapsdDbSyncer m_capsdDbSyncer;
private PluginManager m_pluginManager;
private int m_nodeId;
private static Set<Integer> m_queuedRescanTracker;
/**
* Constructor.
*
* @param nodeInfo
* Scheduler.NodeInfo object containing the nodeid of the node to
* be rescanned.
* @param forceRescan
* True if a forced rescan is to be performed (all interfaces not
* just managed interfaces scanned), false otherwise.
*/
RescanProcessor(Scheduler.NodeInfo nodeInfo, boolean forceRescan, CapsdDbSyncer capsdDbSyncer, PluginManager pluginManager) {
this(nodeInfo.getNodeId(), forceRescan, capsdDbSyncer, pluginManager);
}
/**
* <p>Constructor for RescanProcessor.</p>
*
* @param nodeId a int.
* @param forceRescan a boolean.
* @param capsdDbSyncer a {@link org.opennms.netmgt.capsd.CapsdDbSyncer} object.
* @param pluginManager a {@link org.opennms.netmgt.capsd.PluginManager} object.
*/
public RescanProcessor(int nodeId, boolean forceRescan, CapsdDbSyncer capsdDbSyncer, PluginManager pluginManager) {
m_nodeId = nodeId;
m_forceRescan = forceRescan;
m_capsdDbSyncer = capsdDbSyncer;
m_pluginManager = pluginManager;
// Add the node ID of the node to be rescanned to the Set that tracks
// rescan requests
synchronized (m_queuedRescanTracker) {
m_queuedRescanTracker.add(nodeId);
}
}
/**
* This method is responsible for updating the node table using the most
* recent data collected from the node's managed interfaces.
*
* @param dbc
* Database connection
* @param now
* Date object representing the time of the rescan.
* @param dbNodeEntry
* DbNodeEntry object representing existing values in the
* database
* @param currPrimarySnmpIf
* Primary SNMP interface address based on latest collection
* @param dbIpInterfaces
* Array of DbIpInterfaceEntry objects representing all the
* interfaces retrieved from the database for this node.
* @param collectorMap
* Map of IfCollector objects...one per managed interface.
*
* @return DbNodeEntry object representing the updated values from the node
* table in the database.
*
* @throws SQLException
* if there is a problem updating the node table.
*/
private DbNodeEntry updateNode(Connection dbc, Date now, DbNodeEntry dbNodeEntry, InetAddress currPrimarySnmpIf, DbIpInterfaceEntry[] dbIpInterfaces, Map<String, IfCollector> collectorMap) throws SQLException {
if (log().isDebugEnabled()) {
log().debug("updateNode: updating node id " + dbNodeEntry.getNodeId());
}
/*
* Clone the existing dbNodeEntry so we have all the original
* values of the 'node' table fields in case we need to generate
* 'node***Changed' events following the update.
*/
DbNodeEntry originalDbNodeEntry = DbNodeEntry.clone(dbNodeEntry);
/*
* Create node which represents the most recently retrieved
* information in the collector for this node
*/
DbNodeEntry currNodeEntry = DbNodeEntry.create();
currNodeEntry.setNodeType(DbNodeEntry.NODE_TYPE_ACTIVE);
// Set node label and SMB info based on latest collection
setNodeLabelAndSmbInfo(collectorMap, dbNodeEntry, currNodeEntry, currPrimarySnmpIf);
// Set SNMP info
if (currPrimarySnmpIf != null) {
/*
* We prefer to use the collector for the primary SNMP interface
* to update SNMP data in the node table. However a collector
* for the primary SNMP interface may not exist in the map if
* a node has only recently had SNMP support enabled or if the
* new primary SNMP interface was only recently added to the
* node. At any rate if it exists use it, if not use the
* first collector which supports SNMP.
*/
final String addr = str(currPrimarySnmpIf);
IfCollector primaryIfc = addr == null? null : collectorMap.get(addr);
if (primaryIfc == null) {
for (IfCollector tmp : collectorMap.values()) {
if (tmp.getSnmpCollector() != null) {
primaryIfc = tmp;
break;
}
}
}
/*
* Sanity check...should always have a primary interface
* collector at this point
*/
if (primaryIfc == null) {
log().error("updateNode: failed to determine primary interface collector for node " + dbNodeEntry.getNodeId());
throw new RuntimeException("Update node failed for node " + dbNodeEntry.getNodeId() + ", unable to determine primary interface collector.");
}
IfSnmpCollector snmpc = primaryIfc.getSnmpCollector();
if (snmpc != null && snmpc.hasSystemGroup()) {
SystemGroup sysgrp = snmpc.getSystemGroup();
// sysObjectId
currNodeEntry.setSystemOID(sysgrp.getSysObjectID());
// sysName
String sysName = sysgrp.getSysName();
if (sysName != null && sysName.length() > 0) {
currNodeEntry.setSystemName(sysName);
}
// sysDescription
String sysDescr = sysgrp.getSysDescr();
if (sysDescr != null && sysDescr.length() > 0) {
currNodeEntry.setSystemDescription(sysDescr);
}
// sysLocation
String sysLocation = sysgrp.getSysLocation();
if (sysLocation != null && sysLocation.length() > 0) {
currNodeEntry.setSystemLocation(sysLocation);
}
// sysContact
String sysContact = sysgrp.getSysContact();
if (sysContact != null && sysContact.length() > 0) {
currNodeEntry.setSystemContact(sysContact);
}
}
}
/*
* Currently, we do not use the ParentId except in mapping.
* Unfortunately, this is never
* set in the currNodeEntry so it gets reset here. As a workaround,
* setting it to the old value.
*/
currNodeEntry.updateParentId(dbNodeEntry.getParentId());
// Update any fields which have changed
if (log().isDebugEnabled()) {
log().debug("updateNode: -------dumping old node-------: " + dbNodeEntry);
log().debug("updateNode: -------dumping new node-------: " + currNodeEntry);
}
dbNodeEntry.updateParentId(currNodeEntry.getParentId());
dbNodeEntry.updateNodeType(currNodeEntry.getNodeType());
dbNodeEntry.updateSystemOID(currNodeEntry.getSystemOID());
dbNodeEntry.updateSystemName(currNodeEntry.getSystemName());
dbNodeEntry.updateSystemDescription(currNodeEntry.getSystemDescription());
dbNodeEntry.updateSystemLocation(currNodeEntry.getSystemLocation());
dbNodeEntry.updateSystemContact(currNodeEntry.getSystemContact());
dbNodeEntry.updateNetBIOSName(currNodeEntry.getNetBIOSName());
dbNodeEntry.updateDomainName(currNodeEntry.getDomainName());
dbNodeEntry.updateOS(currNodeEntry.getOS());
dbNodeEntry.setLastPoll(now);
/*
* Only update node label/source if original node entry is
* not set to user-defined.
*/
if (dbNodeEntry.getLabelSource() != DbNodeEntry.LABEL_SOURCE_USER) {
dbNodeEntry.updateLabel(currNodeEntry.getLabel());
dbNodeEntry.updateLabelSource(currNodeEntry.getLabelSource());
}
// Set event flags
boolean nodeLabelChangedFlag = false;
boolean nodeInfoChangedFlag = false;
if (dbNodeEntry.hasLabelChanged() || dbNodeEntry.hasLabelSourceChanged()) {
nodeLabelChangedFlag = true;
}
if (dbNodeEntry.hasSystemOIDChanged() || dbNodeEntry.hasSystemNameChanged() || dbNodeEntry.hasSystemDescriptionChanged() || dbNodeEntry.hasSystemLocationChanged() || dbNodeEntry.hasSystemContactChanged() || dbNodeEntry.hasNetBIOSNameChanged() || dbNodeEntry.hasDomainNameChanged() || dbNodeEntry.hasOSChanged()) {
nodeInfoChangedFlag = true;
}
// Call store to update the database
dbNodeEntry.store(dbc);
// Create nodeLabelChanged event if necessary
if (nodeLabelChangedFlag) {
m_eventList.add(createNodeLabelChangedEvent(dbNodeEntry, originalDbNodeEntry));
}
// Create nodeInfoChangedEvent if necessary
if (nodeInfoChangedFlag) {
m_eventList.add(createNodeInfoChangedEvent(dbNodeEntry, originalDbNodeEntry));
}
return dbNodeEntry;
}
/**
* This method is responsible for updating all of the interface's associated
* with a node.
*
* @param dbc
* Database connection.
* @param now
* Date/time to be associated with the update.
* @param node
* Node entry for the node being rescanned
* @param collectorMap
* Map of IfCollector objects associated with the node.
* @param doesSnmp
* Indicates that the interface does support SNMP
*
* @throws SQLException
* if there is a problem updating the ipInterface table.
*/
private void updateInterfaces(Connection dbc, Date now, DbNodeEntry node,
Map<String, IfCollector> collectorMap, boolean doesSnmp)
throws SQLException {
/*
* make sure we have a current PackageIpListMap
* this was getting done once for each managed ip
* interface in updateInterfaceInfo. Seems more
* efficient to just do it once here, and then later
* for new interfaces (which aren't in the DB yet at
* this point) in updateInterfaceInfo.
*/
log().debug("updateInterfaces: Rebuilding PackageIpListMap");
PollerConfig pollerCfgFactory = PollerConfigFactory.getInstance();
pollerCfgFactory.rebuildPackageIpListMap();
/*
* List of update interfaces
* This list is maintained so that for nodes with multiple
* interfaces which support SNMP, interfaces are not updated
* more than once.
*/
List<InetAddress> updatedIfList = new ArrayList<InetAddress>();
IfSnmpCollector snmpCollector = null;
if (doesSnmp) {
/*
* Reset modification flags. These flags are set by
* the updateInterface() method when changes have been
* detected which warrant further action (such as
* generating an event).
*/
m_ifIndexOnNodeChangedFlag = false;
m_snmpIfTableChangedFlag = false;
/*
* Determine if any of the interface collector objects have
* an SNMP collector associated with them. If so, use the first
* interface with SNMP data collected to update all SNMP-found
* interfaces.
*/
IfCollector collectorWithSnmp = null;
for (IfCollector tmp : collectorMap.values()) {
if (tmp.getSnmpCollector() != null) {
collectorWithSnmp = tmp;
break;
}
}
if (collectorWithSnmp != null) {
snmpCollector = collectorWithSnmp.getSnmpCollector();
updateInterface(dbc, now, node, collectorWithSnmp.getTarget(),
collectorWithSnmp.getTarget(),
collectorWithSnmp.getSupportedProtocols(),
snmpCollector, doesSnmp);
updatedIfList.add(collectorWithSnmp.getTarget());
// Update subtargets
if (collectorWithSnmp.hasAdditionalTargets()) {
Map<InetAddress, List<SupportedProtocol>> subTargets = collectorWithSnmp.getAdditionalTargets();
for(InetAddress subIf : subTargets.keySet()) {
updateInterface(dbc, now, node,
collectorWithSnmp.getTarget(), subIf,
subTargets.get(subIf),
snmpCollector, doesSnmp);
updatedIfList.add(subIf);
}
}
// Add any new non-IP interfaces
if (collectorWithSnmp.hasNonIpInterfaces()) {
for(Integer ifIndex : collectorWithSnmp.getNonIpInterfaces()) {
updateNonIpInterface(dbc, now, node, ifIndex.intValue(),
snmpCollector);
}
}
}
}
/*
* Majority of interfaces should have been updated by this
* point (provided the node supports SNMP). Only non-SNMP
* interfaces and those associated with the node via
* SMB (NetBIOS name) should remain. Loop through collector
* map and update any remaining interfaces. Use the
* updatedIfList object to filter out any interfaces which
* have already been updated
*/
// Iterate over interfaces from collection map
for (IfCollector ifc : collectorMap.values()) {
// Update target
InetAddress ifaddr = ifc.getTarget();
if (!updatedIfList.contains(ifaddr)) {
updateInterface(dbc, now, node, ifc.getTarget(), ifaddr,
ifc.getSupportedProtocols(), snmpCollector,
doesSnmp);
updatedIfList.add(ifaddr);
}
// Update subtargets
if (ifc.hasAdditionalTargets()) {
Map<InetAddress, List<SupportedProtocol>> subTargets = ifc.getAdditionalTargets();
for(InetAddress subIf : subTargets.keySet()) {
if (!updatedIfList.contains(subIf)) {
updateInterface(dbc, now, node, ifc.getTarget(), subIf,
subTargets.get(subIf),
snmpCollector, doesSnmp);
updatedIfList.add(subIf);
}
}
}
}
}
/**
* This method is responsible for updating the ipInterface table entry for a
* specific interface.
*
* @param dbc
* Database Connection
* @param now
* Date/time to be associated with the update.
* @param node
* Node entry for the node being rescanned
* @param ifIndex
* Interface index of non-IP interface to update
* @param snmpc
* SNMP collector or null if SNMP not supported.
*
* @throws SQLException
* if there is a problem updating the ipInterface table.
*/
private void updateNonIpInterface(Connection dbc, Date now,
DbNodeEntry node, int ifIndex, IfSnmpCollector snmpc)
throws SQLException {
if (log().isDebugEnabled()) {
log().debug("updateNonIpInterface: node= " + node.getNodeId()
+ " ifIndex= " + ifIndex);
}
// Sanity Check
if (snmpc == null || snmpc.failed()) {
return;
}
// Construct InetAddress object for "0.0.0.0" address
InetAddress ifAddr = null;
ifAddr = ZERO_ZERO_ZERO_ZERO;
if (ifAddr == null) return;
updateSnmpInfoForNonIpInterface(dbc, node, ifIndex, snmpc, ifAddr);
}
/**
* SnmpInterface table updates for non-IP interface.
*/
private void updateSnmpInfoForNonIpInterface(Connection dbc,
DbNodeEntry node, int ifIndex, IfSnmpCollector snmpc,
InetAddress ifAddr) throws SQLException {
if (log().isDebugEnabled()) {
log().debug("updateNonIpInterface: updating non-IP SNMP interface "
+ "with nodeId=" + node.getNodeId() + " and ifIndex="
+ ifIndex);
}
// Create and load SNMP Interface entry from the database
boolean newSnmpIfTableEntry = false;
DbSnmpInterfaceEntry dbSnmpIfEntry = DbSnmpInterfaceEntry.get(dbc,node.getNodeId(), ifIndex);
if (dbSnmpIfEntry == null) {
/*
* SNMP Interface not found with this nodeId & ifIndex, create new
* interface
*/
if (log().isDebugEnabled()) {
log().debug("updateNonIpInterface: non-IP SNMP interface with "
+ "ifIndex " + ifIndex+ " not in database, creating "
+ "new snmpInterface object.");
}
dbSnmpIfEntry = DbSnmpInterfaceEntry.create(node.getNodeId(), ifIndex);
newSnmpIfTableEntry = true;
}
IfTableEntry ifte = findEntryByIfIndex(ifIndex, snmpc);
IfXTableEntry ifxte = findXEntryByIfIndex(ifIndex, snmpc);
/*
* Make sure we have a valid IfTableEntry object and update
* any values which have changed
*/
if (ifte != null) {
// index
// dbSnmpIfEntry.updateIfIndex(ifIndex);
/*
* netmask
*
* NOTE: non-IP interfaces don't have netmasks so skip
*/
updateType(ifte, dbSnmpIfEntry);
updateDescription(ifIndex, ifte, dbSnmpIfEntry);
updatePhysicalAddress(ifIndex, ifte, dbSnmpIfEntry);
updateSpeed(ifIndex, ifte, ifxte, dbSnmpIfEntry);
updateAdminStatus(ifte, dbSnmpIfEntry);
updateOperationalStatus(ifte, dbSnmpIfEntry);
updateName(ifIndex, snmpc, dbSnmpIfEntry);
updateAlias(ifIndex, snmpc, dbSnmpIfEntry);
} // end if valid ifTable entry
/*
* If this is a new interface or if any of the following
* key fields have changed set the m_snmpIfTableChangedFlag
* variable to TRUE. This will potentially trigger an event
* which will cause the poller to reinitialize the primary
* SNMP interface for the node.
*/
// dbSnmpIfEntry.hasIfIndexChanged() ||
if (!m_snmpIfTableChangedFlag
&& newSnmpIfTableEntry
|| dbSnmpIfEntry.hasTypeChanged()
|| dbSnmpIfEntry.hasNameChanged()
|| dbSnmpIfEntry.hasDescriptionChanged()
|| dbSnmpIfEntry.hasPhysicalAddressChanged()
|| dbSnmpIfEntry.hasAliasChanged()) {
m_snmpIfTableChangedFlag = true;
}
// Update the database
dbSnmpIfEntry.store(dbc);
}
/**
* Find the ifTable entry for this interface.
*/
private static IfTableEntry findEntryByIfIndex(int ifIndex, IfSnmpCollector snmpc) {
if (snmpc.hasIfTable()) {
return snmpc.getIfTable().getEntry(ifIndex);
}
return null;
}
/**
* Find the ifXTable entry for this interface.
*/
private static IfXTableEntry findXEntryByIfIndex(int ifIndex, IfSnmpCollector snmpc) {
if (snmpc.hasIfXTable()) {
return snmpc.getIfXTable().getEntry(ifIndex);
}
return null;
}
private static void updateAlias(int ifIndex, IfSnmpCollector snmpc, DbSnmpInterfaceEntry dbSnmpIfEntry) {
// alias (from interface extensions table)
String ifAlias = snmpc.getIfAlias(ifIndex);
if (ifAlias != null) {
dbSnmpIfEntry.updateAlias(ifAlias);
} else {
dbSnmpIfEntry.updateAlias("");
}
}
private static void updateName(int ifIndex, IfSnmpCollector snmpc, DbSnmpInterfaceEntry dbSnmpIfEntry) {
// name (from interface extensions table)
String ifName = snmpc.getIfName(ifIndex);
if (ifName != null && ifName.length() > 0) {
dbSnmpIfEntry.updateName(ifName);
}
}
private static void updateOperationalStatus(IfTableEntry ifte, DbSnmpInterfaceEntry dbSnmpIfEntry) {
Integer sint = ifte.getIfOperStatus();
if (sint == null) {
dbSnmpIfEntry.updateOperationalStatus(0);
} else {
dbSnmpIfEntry.updateOperationalStatus(sint.intValue());
}
}
private static void updateAdminStatus(IfTableEntry ifte, DbSnmpInterfaceEntry dbSnmpIfEntry) {
Integer sint = ifte.getIfAdminStatus();
if (sint == null) {
dbSnmpIfEntry.updateAdminStatus(0);
} else {
dbSnmpIfEntry.updateAdminStatus(sint.intValue());
}
}
private static void updateType(IfTableEntry ifte, DbSnmpInterfaceEntry dbSnmpIfEntry) {
Integer sint = ifte.getIfType();
if (sint == null) {
dbSnmpIfEntry.updateType(0);
} else {
dbSnmpIfEntry.updateType(sint.intValue());
}
}
private static void updateDescription(int ifIndex, IfTableEntry ifte, DbSnmpInterfaceEntry dbSnmpIfEntry) {
String str = ifte.getIfDescr();
if (log().isDebugEnabled()) {
log().debug("updateNonIpInterface: ifIndex: " + ifIndex + " has ifDescription: " + str);
}
if (str != null && str.length() > 0) {
dbSnmpIfEntry.updateDescription(str);
}
}
private static void updatePhysicalAddress(int ifIndex, IfTableEntry ifte, DbSnmpInterfaceEntry dbSnmpIfEntry) {
String physAddr = ifte.getPhysAddr();
if (log().isDebugEnabled()) {
log().debug("updateNonIpInterface: ifIndex: " + ifIndex + " has physical address '" + physAddr + "'");
}
if (physAddr != null && physAddr.length() == 12) {
dbSnmpIfEntry.updatePhysicalAddress(physAddr);
}
}
static void updateSpeed(int ifIndex, IfTableEntry ifte, IfXTableEntry ifxte, DbSnmpInterfaceEntry dbSnmpIfEntry) {
long speed = 0;
try {
speed = getInterfaceSpeed(ifte, ifxte);
} catch (Throwable e) {
log().warn("updateNonIpInterface: ifSpeed '" + ifte.getDisplayString(IfTableEntry.IF_SPEED) + "' for ifIndex " + ifIndex + " is invalid, inserting 0: " + e, e);
speed = 0;
}
dbSnmpIfEntry.updateSpeed(speed);
}
private static long getInterfaceSpeed(IfTableEntry ifte, IfXTableEntry ifxte) {
if (ifxte != null && ifxte.getIfHighSpeed() != null && ifxte.getIfHighSpeed() > 4294) {
return ifxte.getIfHighSpeed() * 1000000L;
}
if (ifte != null && ifte.getIfSpeed() != null) {
return ifte.getIfSpeed();
}
return 0;
}
private static ThreadCategory log() {
return ThreadCategory.getInstance(RescanProcessor.class);
}
/**
* This method is responsible for updating the ipInterface table entry for a
* specific interface.
*
* @param dbc
* Database Connection
* @param now
* Date/time to be associated with the update.
* @param node
* Node entry for the node being rescanned
* @param target
* Target interface (from IfCollector.getTarget())
* @param ifaddr
* Interface being updated.
* @param protocols
* Protocols supported by the interface.
* @param snmpc
* SNMP collector or null if SNMP not supported.
* @param doesSnmp
* Indicates that the interface supports SNMP
*
* @throws SQLException
* if there is a problem updating the ipInterface table.
*/
private void updateInterface(Connection dbc, Date now, DbNodeEntry node,
InetAddress target, InetAddress ifaddr, List<SupportedProtocol> protocols,
IfSnmpCollector snmpc, boolean doesSnmp) throws SQLException {
/*
* Reparenting
*
* This sub-interface was not previously associated with this node. If
* the sub-interface is already associated with another node we must do
* one of the following:
*
* 1. If the target interface (the one being rescanned) appears to be an
* interface alias all of the interfaces under the sub-interface's node
* will be reparented under the nodeid of the target interface.
*
* 2. If however the interface is not an alias, only the sub-interface
* will be reparented under the nodeid of the interface being rescanned.
*
* In the reparenting process, the database ipinterface, snmpinterface
* and ifservices table entries associated with the reparented interface
* will be "updated" to reflect the new nodeid. If the old node has
* no remaining interfaces following the reparenting it will be marked
* as deleted.
*/
/*
* Special case: Need to skip interface reparenting for '0.0.0.0'
* interfaces as well as loopback interfaces ('127.*.*.*').
*/
final String ifaddrString = str(ifaddr);
if (log().isDebugEnabled()) {
log().debug("updateInterface: updating interface "
+ ifaddrString + "(targetIf="
+ str(target) + ")");
if (doesSnmp) {
log().debug("updateInterface: the SNMP collection passed in is "
+ "collected via "
+ (snmpc == null ? "No SnmpCollection passed in (snmpc == null)" : str(snmpc.getCollectorTargetAddress())));
}
}
boolean reparentFlag = false;
boolean newIpIfEntry = false;
int ifIndex = -1;
DbIpInterfaceEntry dbIpIfEntry =
DbIpInterfaceEntry.get(dbc,node.getNodeId(), ifaddr);
if (doesSnmp && snmpc != null && snmpc.hasIpAddrTable()) {
// Attempt to load IP Interface entry from the database
ifIndex = snmpc.getIfIndex(ifaddr);
if (log().isDebugEnabled()) {
log().debug("updateInterface: interface = "
+ ifaddrString + " ifIndex = " + ifIndex
+ ". Checking for this address on other nodes.");
}
/*
* the updating interface may have already existed in the
* ipinterface table with different
* nodeIds. If it exist in a different node, verify if all the
* interfaces on that node
* are contained in the snmpc of the updating interface. If they
* are, reparent all
* the interfaces on that node to the node of the updating
* interface, otherwise, just add
* the interface to the updating node.
*/
// Verify that SNMP collection contains ipAddrTable entries
IpAddrTable ipAddrTable = null;
ipAddrTable = snmpc.getIpAddrTable();
if (ipAddrTable == null) {
log().error("updateInterface: null ipAddrTable in the SNMP "
+ "collection");
} else {
if (ifaddrString.equals("0.0.0.0") || ifaddr.isLoopbackAddress()) {
if (log().isDebugEnabled()) {
log().debug("updateInterface: Skipping address from "
+ "snmpc ipAddrTable "
+ ifaddrString);
}
} else {
if (log().isDebugEnabled()) {
log().debug("updateInterface: Checking address from "
+ "snmpc ipAddrTable "
+ ifaddrString);
}
PreparedStatement stmt = null;
final DBUtils d = new DBUtils(RescanProcessor.class);
try {
stmt = dbc.prepareStatement(SQL_DB_RETRIEVE_OTHER_NODES);
d.watch(stmt);
stmt.setString(1, ifaddrString);
stmt.setInt(2, node.getNodeId());
ResultSet rs = stmt.executeQuery();
d.watch(rs);
while (rs.next()) {
int existingNodeId = rs.getInt(1);
if (log().isDebugEnabled()) {
log().debug("updateInterface: ckecking for "
+ ifaddrString
+ " on existing nodeid "
+ existingNodeId);
}
DbNodeEntry suspectNodeEntry = DbNodeEntry.get(dbc, existingNodeId);
if (suspectNodeEntry == null) {
// This can happen if a node has been deleted.
continue;
}
/*
* Retrieve list of interfaces associated with the
* old node
*/
DbIpInterfaceEntry[] tmpIfArray = suspectNodeEntry.getInterfaces(dbc);
/*
* Verify if the suspectNodeEntry is a duplicate
* node
*/
if (areDbInterfacesInSnmpCollection(tmpIfArray, snmpc)) {
/*
* Reparent each interface under the targets'
* nodeid
*/
for (int i = 0; i < tmpIfArray.length; i++) {
InetAddress addr = tmpIfArray[i].getIfAddress();
int index = snmpc.getIfIndex(addr);
// Skip non-IP or loopback interfaces
final String addrString = str(addr);
if (addrString == null || addrString.equals("0.0.0.0") || addr.isLoopbackAddress()) {
continue;
}
if (log().isDebugEnabled()) {
log().debug("updateInterface: "
+ "reparenting interface "
+ addrString
+ " under node: "
+ node.getNodeId()
+ " from existing node: "
+ existingNodeId);
}
reparentInterface(dbc, addr, index, node.getNodeId(), existingNodeId);
// Create interfaceReparented event
createInterfaceReparentedEvent(node, existingNodeId, addr);
}
if (log().isDebugEnabled()) {
log().debug("updateInterface: interface "
+ ifaddrString
+ " is added to node: "
+ node.getNodeId()
+ " by reparenting from existing "
+ "node: " + existingNodeId);
}
dbIpIfEntry = DbIpInterfaceEntry.get(dbc, node.getNodeId(), ifaddr);
reparentFlag = true;
// delete duplicate node after reparenting.
deleteDuplicateNode(dbc, suspectNodeEntry);
createDuplicateNodeDeletedEvent(suspectNodeEntry);
}
}
}
catch (SQLException e) {
log().error("SQLException while updating interface: " + ifaddrString + " on nodeid: " + node.getNodeId());
throw e;
} finally {
d.cleanUp();
}
}
}
}
/*
* if no reparenting occurred on the updating interface, add it to the
* updating node.
*/
if (dbIpIfEntry == null) {
/*
* Interface not found with this nodeId so create new interface
* entry
*/
if (log().isDebugEnabled()) {
log().debug("updateInterface: interface " + ifaddr + " ifIndex "
+ ifIndex + " not in database under nodeid "
+ node.getNodeId()
+ ", creating new interface object.");
}
/*
* If doesSnmp is set to true, the dbIpIfEntry must not be stored
* to the database until the corresponding DbSnmpInterfaceEntry is
* stored.
*/
if (ifIndex == -1 && !doesSnmp) {
dbIpIfEntry = DbIpInterfaceEntry.create(node.getNodeId(),
ifaddr);
} else {
dbIpIfEntry = DbIpInterfaceEntry.create(node.getNodeId(),
ifaddr, ifIndex);
/*
* XXX uh, what????? - dj@opennms.org
* This wasn't getting done for some reason, so do it explicitly
*/
dbIpIfEntry.setIfIndex(ifIndex);
}
if (isDuplicateInterface(dbc, ifaddr, node.getNodeId())) {
m_eventList.add(createDuplicateIpAddressEvent(dbIpIfEntry));
}
newIpIfEntry = true;
}
DbIpInterfaceEntry currIpIfEntry =
getNewDbIpInterfaceEntry(node, snmpc, doesSnmp, ifaddr);
/*
* XXX Note that updateSnmpInfo only gets called if doesSnmp is
* true, but a new dbIpIfEntry with an ifIndex might have been
* create()ed above if ifIndex != -1 || doesSnmp. This might be
* a problem if doesSnmp is false but ifIndex != -1, as the ipInterface
* entry will point an snmpInterface entry that might not exist.
*/
if (doesSnmp && snmpc != null) {
// update SNMP info if available
updateSnmpInfo(dbc, node, snmpc, currIpIfEntry.getIfAddress(),
currIpIfEntry.getIfIndex());
}
// update ipinterface for the updating interface
updateInterfaceInfo(dbc, now, node, dbIpIfEntry, currIpIfEntry,
newIpIfEntry, reparentFlag);
// update IfServices for the updating interface
updateServiceInfo(dbc, node, dbIpIfEntry, newIpIfEntry, protocols);
}
/**
* This method is responsible to delete any interface associated with the
* duplicate node, delete any entry left in ifservices table and
* snmpinterface table for the duplicate node, and make the node as
* 'deleted'.
*
* @param dbc
* Database Connection
* @param duplicateNode
* Duplicate node to delete.
*
*/
private static void deleteDuplicateNode(Connection dbc, DbNodeEntry duplicateNode) throws SQLException {
final DBUtils d = new DBUtils(RescanProcessor.class);
try {
PreparedStatement ifStmt = dbc.prepareStatement(SQL_DB_DELETE_DUP_INTERFACE);
d.watch(ifStmt);
PreparedStatement svcStmt = dbc.prepareStatement(SQL_DB_DELETE_DUP_SERVICES);
d.watch(svcStmt);
PreparedStatement snmpStmt = dbc.prepareStatement(SQL_DB_DELETE_DUP_SNMPINTERFACE);
d.watch(snmpStmt);
ifStmt.setInt(1, duplicateNode.getNodeId());
svcStmt.setInt(1, duplicateNode.getNodeId());
snmpStmt.setInt(1, duplicateNode.getNodeId());
ifStmt.executeUpdate();
svcStmt.executeUpdate();
snmpStmt.executeUpdate();
duplicateNode.setNodeType(DbNodeEntry.NODE_TYPE_DELETED);
duplicateNode.store(dbc);
} catch (SQLException sqlE) {
log().error("deleteDuplicateNode SQLException while deleting duplicate node: " + duplicateNode.getNodeId());
throw sqlE;
} finally {
d.cleanUp();
}
}
/**
* This method verify if an ipaddress is existing in other node except in
* the updating node.
*
* @param dbc
* Database Connection
* @param ifaddr
* Ip address being verified.
* @param nodeId
* Node Id of the node being rescanned
*
*/
private static boolean isDuplicateInterface(Connection dbc, InetAddress ifaddr, int nodeId) throws SQLException {
boolean duplicate = false;
PreparedStatement stmt = null;
final DBUtils d = new DBUtils(RescanProcessor.class);
try {
stmt = dbc.prepareStatement(SQL_DB_RETRIEVE_OTHER_NODES);
d.watch(stmt);
stmt.setString(1, str(ifaddr));
stmt.setInt(2, nodeId);
ResultSet rs = stmt.executeQuery();
d.watch(rs);
while (rs.next()) {
duplicate = true;
}
return duplicate;
} catch (SQLException sqlE) {
log().error("isDuplicateInterface: SQLException while updating interface: " + str(ifaddr) + " on nodeid: " + nodeId);
throw sqlE;
} finally {
d.cleanUp();
}
}
/**
* This method is responsible for updating the ipinterface table entry for a
* specific interface.
*
* @param dbc
* Database Connection.
* @param now
* Date/time to be associated with the update.
* @param node
* Node entry for the node being rescanned.
* @param dbIpIfEntry
* interface entry of the updating interface.
* @param snmpc
* SNMP collector or null if SNMP not supported.
* @param isNewIpEntry
* if dbIpIfEntry is a new entry.
* @param isReparented
* if dbIpIfEntry is reparented.
* @param doesSnmp
* if node supports SNMP.
*
* @throws SQLException
* if there is a problem updating the ipinterface table.
*/
private void updateInterfaceInfo(Connection dbc, Date now, DbNodeEntry node,
DbIpInterfaceEntry dbIpIfEntry, DbIpInterfaceEntry currIpIfEntry,
boolean isNewIpEntry, boolean isReparented)
throws SQLException {
PollerConfig pollerCfgFactory = PollerConfigFactory.getInstance();
InetAddress ifaddr = dbIpIfEntry.getIfAddress();
/*
* Clone the existing database entry so we have access to the values
* of the database fields associated with the interface in the event
* that something has changed.
*/
DbIpInterfaceEntry originalIpIfEntry = DbIpInterfaceEntry.clone(dbIpIfEntry);
// Update any fields which have changed
dbIpIfEntry.setLastPoll(now);
dbIpIfEntry.updateHostname(currIpIfEntry.getHostname());
dbIpIfEntry.updateManagedState(currIpIfEntry.getManagedState());
dbIpIfEntry.updateStatus(currIpIfEntry.getStatus());
dbIpIfEntry.updatePrimaryState(currIpIfEntry.getPrimaryState());
/*
* XXX Note: the ifIndex will not be updated if updateIfIndex(-1)
* is called. In other words, an ifIndex of a value other than -1
* (non-null in the database) will never change to -1 (which is null
* in the database) by calling updateIfIndex. setIfIndex does work,
* however if m_useIfIndexAsKey is set in the DbIpInterfaceEntry,
* no entries (or at least not the right entry) will be updated
* because the WHERE clause for the UPDATE will be referring to the
* *new* ifIndex.
*/
dbIpIfEntry.updateIfIndex(currIpIfEntry.getIfIndex());
/*
* Set event flags
* NOTE: Must set these flags prior to call to
* DbIpInterfaceEntry.store()
* method which will cause the change map to be cleared.
*/
boolean ifIndexChangedFlag = false;
boolean ipHostnameChangedFlag = false;
if (dbIpIfEntry.hasIfIndexChanged()) {
ifIndexChangedFlag = true;
}
if (dbIpIfEntry.hasHostnameChanged()) {
ipHostnameChangedFlag = true;
}
// Update the database
dbIpIfEntry.store(dbc);
/*
* If the interface was not already in the database under
* the node being rescanned or some other node send a
* nodeGainedInterface event.
*/
if (isNewIpEntry && !isReparented) {
createNodeGainedInterfaceEvent(dbIpIfEntry);
}
// InterfaceIndexChanged event
if (log().isDebugEnabled()) {
log().debug("updateInterfaceInfo: ifIndex changed: "
+ ifIndexChangedFlag);
}
if (ifIndexChangedFlag) {
m_eventList.add(createInterfaceIndexChangedEvent(dbIpIfEntry, originalIpIfEntry));
m_ifIndexOnNodeChangedFlag = true;
}
// IPHostNameChanged event
if (log().isDebugEnabled()) {
log().debug("updateInterfaceInfo: hostname changed: "
+ ipHostnameChangedFlag);
}
if (ipHostnameChangedFlag) {
m_eventList.add(createIpHostNameChangedEvent(dbIpIfEntry, originalIpIfEntry));
}
if (isNewIpEntry) {
/*
* If it's new, the packageIpListMap needs to be rebuilt,
* polling status rechecked, and ismanaged updated if necessary
*/
boolean ipToBePolled = false;
final String ifaddrString = str(ifaddr);
log().debug("updateInterfaceInfo: rebuilding PackageIpListMap for "
+ "new interface " + ifaddrString);
PollerConfigFactory.getInstance().rebuildPackageIpListMap();
org.opennms.netmgt.config.poller.Package ipPkg = ifaddrString == null? null : pollerCfgFactory.getFirstPackageMatch(ifaddrString);
if (ipPkg != null) {
ipToBePolled = true;
}
if (log().isDebugEnabled()) {
log().debug("updateInterfaceInfo: interface " + ifaddrString + " to be polled: " + ipToBePolled);
}
if (ipToBePolled) {
final DBUtils d = new DBUtils(RescanProcessor.class);
try {
PreparedStatement stmt = dbc.prepareStatement(SQL_DB_UPDATE_ISMANAGED);
d.watch(stmt);
stmt.setString(1, new String(new char[] { DbIpInterfaceEntry.STATE_MANAGED }));
stmt.setLong(2, dbIpIfEntry.getNodeId());
stmt.setString(3, ifaddrString);
stmt.executeUpdate();
if (log().isDebugEnabled()) {
log().debug("updateInterfaceInfo: updated managed state "
+ "for new interface "
+ ifaddrString + " on node "
+ dbIpIfEntry.getNodeId() + " to managed");
}
} finally {
d.cleanUp();
}
}
}
}
/**
* Create IP interface entry representing latest information
* retrieved for the interface via the collector. If doesSnmp is set to
* <i>true</i>, this entry must <b>not</b> be stored to the database until
* the corresponding DbSnmpInterfaceEntry is stored.
*/
private static DbIpInterfaceEntry getNewDbIpInterfaceEntry(DbNodeEntry node,
IfSnmpCollector snmpc, boolean doesSnmp,
InetAddress ifaddr) {
CapsdConfig cFactory = CapsdConfigFactory.getInstance();
PollerConfig pollerCfgFactory = PollerConfigFactory.getInstance();
int ifIndex = -1;
DbIpInterfaceEntry currIpIfEntry;
final String ifaddrString = str(ifaddr);
if (doesSnmp) {
if (snmpc != null && snmpc.hasIpAddrTable()) {
ifIndex = snmpc.getIfIndex(ifaddr);
}
if (ifIndex == -1) {
if (log().isDebugEnabled()) {
log().debug("updateInterfaceInfo: interface "
+ ifaddrString
+ " has no valid ifIndex. Assuming this is a "
+ "lame SNMP host with no ipAddrTable");
}
ifIndex = CapsdConfig.LAME_SNMP_HOST_IFINDEX;
}
currIpIfEntry = DbIpInterfaceEntry.create(node.getNodeId(), ifaddr, ifIndex);
} else {
currIpIfEntry = DbIpInterfaceEntry.create(node.getNodeId(), ifaddr);
}
// Hostname
currIpIfEntry.setHostname(ifaddr.getHostName());
/*
* Managed state
* NOTE: (reference internal bug# 201)
* If the ip is 'managed', it might still be 'not polled' based
* on the poller configuration.
*
* Try to avoid re-evaluating the ip against filters for
* each service, try to get the first package here and use
* that for service evaluation
*
* At this point IF the ip is already in the database, package filter
* evaluation should go through OK. New interfaces will be dealt with
* later
*/
org.opennms.netmgt.config.poller.Package ipPkg = null;
if (cFactory.isAddressUnmanaged(ifaddr)) {
currIpIfEntry.setManagedState(DbIpInterfaceEntry.STATE_UNMANAGED);
} else {
boolean ipToBePolled = false;
ipPkg = ifaddrString == null? null : pollerCfgFactory.getFirstPackageMatch(ifaddrString);
if (ipPkg != null) {
ipToBePolled = true;
}
if (ipToBePolled) {
currIpIfEntry.setManagedState(DbIpInterfaceEntry.STATE_MANAGED);
} else {
currIpIfEntry.setManagedState(DbIpInterfaceEntry.STATE_NOT_POLLED);
}
if (log().isDebugEnabled()) {
log().debug("updateInterfaceInfo: interface "
+ ifaddrString + " to be polled = "
+ ipToBePolled);
}
}
/*
* If SNMP data collection is available set SNMP Primary state
* as well as ifIndex and ifStatus.
*
* For all interfaces simply set 'isSnmpPrimary' field to
* not eligible for now. Following the interface updates
* the primary and secondary SNMP interfaces will be
* determined and the value of the 'isSnmpPrimary' field
* set accordingly for each interface. The old primary
* interface should have already been saved for future
* reference.
*/
if (doesSnmp && snmpc != null && snmpc.hasIpAddrTable()) {
if (ifIndex != -1) {
if (snmpc.hasIfTable()) {
int status = snmpc.getAdminStatus(ifIndex);
currIpIfEntry.setStatus(status);
}
} else {
// No ifIndex found
log().debug("updateInterfaceInfo: No ifIndex found for "
+ ifaddrString
+ ". Not eligible for primary SNMP interface.");
}
currIpIfEntry.setPrimaryState(DbIpInterfaceEntry.SNMP_NOT_ELIGIBLE);
} else if (doesSnmp) {
currIpIfEntry.setPrimaryState(DbIpInterfaceEntry.SNMP_NOT_ELIGIBLE);
}
return currIpIfEntry;
}
/**
* This method is responsible for updating the ifservices table entry for a
* specific interface.
*
* @param dbc
* Database Connection.
* @param node
* Node entry for the node being rescanned.
* @param dbIpIfEntry
* interface entry of the updating interface.
* @param isNewIpEntry
* if the dbIpIfEntry is a new entry.
* @param protocols
* Protocols supported by the interface.
*
* @throws SQLException
* if there is a problem updating the ifservices table.
*/
private void updateServiceInfo(Connection dbc, DbNodeEntry node, DbIpInterfaceEntry dbIpIfEntry, boolean isNewIpEntry, List<SupportedProtocol> protocols) throws SQLException {
CapsdConfig cFactory = CapsdConfigFactory.getInstance();
PollerConfig pollerCfgFactory = PollerConfigFactory.getInstance();
org.opennms.netmgt.config.poller.Package ipPkg = null;
InetAddress ifaddr = dbIpIfEntry.getIfAddress();
// Retrieve from the database the interface's service list
DbIfServiceEntry[] dbSupportedServices = dbIpIfEntry.getServices(dbc);
int ifIndex = dbIpIfEntry.getIfIndex();
if (log().isDebugEnabled()) {
if (ifIndex == -1) {
log().debug("updateServiceInfo: Retrieving interface's service list from database for host " + dbIpIfEntry.getHostname());
} else {
log().debug("updateServiceInfo: Retrieving interface's service list from database for host " + dbIpIfEntry.getHostname() + " ifindex " + ifIndex);
}
}
/*
* add newly supported protocols
*
* NOTE!!!!!: (reference internal bug# 201)
* If the ip is 'managed', the service can still be 'not polled'
* based on the poller configuration - at this point the ip is already
* in the database, so package filter evaluation should go through OK
*/
if (log().isDebugEnabled()) {
log().debug("updateServiceInfo: Checking for new services on host "
+ dbIpIfEntry.getHostname());
}
Iterator<SupportedProtocol> iproto = protocols.iterator();
while (iproto.hasNext()) {
SupportedProtocol p = iproto.next();
Number sid = m_capsdDbSyncer.getServiceId(p.getProtocolName());
/*
* Only adding newly supported services so check against the service
* list retrieved from the database
*/
boolean found = false;
for (int i = 0; i < dbSupportedServices.length && !found; i++) {
if (dbSupportedServices[i].getServiceId() == sid.intValue()) {
found = true;
}
}
if (!found) {
DbIfServiceEntry ifSvcEntry = DbIfServiceEntry.create(node.getNodeId(), ifaddr, sid.intValue());
// now fill in the entry
final String ifaddrString = str(ifaddr);
if (cFactory.isAddressUnmanaged(ifaddr)) {
ifSvcEntry.setStatus(DbIfServiceEntry.STATUS_UNMANAGED);
} else {
ipPkg = ifaddrString == null? null : pollerCfgFactory.getFirstPackageMatch(ifaddrString);
if (ipPkg == null) {
ifSvcEntry.setStatus(DbIfServiceEntry.STATUS_NOT_POLLED);
} else if (isServicePolledLocally(ifaddrString, p.getProtocolName(), ipPkg)) {
ifSvcEntry.setStatus(DbIfServiceEntry.STATUS_ACTIVE);
} else if (isServicePolled(ifaddrString, p.getProtocolName(), ipPkg)) {
ifSvcEntry.setStatus(DbIpInterfaceEntry.STATE_REMOTE);
} else {
ifSvcEntry.setStatus(DbIfServiceEntry.STATUS_NOT_POLLED);
}
}
/*
* Set qualifier if available. Currently the qualifier field
* is used to store the port at which the protocol was found.
*/
if (p.getQualifiers() != null && p.getQualifiers().get("port") != null) {
try {
Integer port = (Integer) p.getQualifiers().get("port");
if (log().isDebugEnabled()) {
log().debug("updateServiceInfo: got a port qualifier: " + port + " for service: " + p.getProtocolName());
}
ifSvcEntry.setQualifier(port.toString());
} catch (ClassCastException ccE) {
// Do nothing
}
}
ifSvcEntry.setSource(DbIfServiceEntry.SOURCE_PLUGIN);
ifSvcEntry.setNotify(DbIfServiceEntry.NOTIFY_ON);
if (ifIndex != -1) {
ifSvcEntry.setIfIndex(ifIndex);
}
ifSvcEntry.store();
if (log().isDebugEnabled()) {
log().debug("updateIfServices: update service: " + p.getProtocolName() + " for interface:" + ifaddrString + " on node:" + node.getNodeId());
}
// Generate nodeGainedService event
m_eventList.add(createNodeGainedServiceEvent(node, dbIpIfEntry, p.getProtocolName()));
/*
* If this interface already existed in the database and SNMP
* service has been gained then create interfaceSupportsSNMP
* event
*/
if (!isNewIpEntry && p.getProtocolName().equalsIgnoreCase("SNMP")) {
m_eventList.add(createInterfaceSupportsSNMPEvent(dbIpIfEntry));
}
}
// Update the supported services list
dbSupportedServices = dbIpIfEntry.getServices(dbc);
} // end while(more protocols)
if (m_forceRescan) {
updateServicesOnForcedRescan(node, dbIpIfEntry, dbSupportedServices);
}
}
private static boolean isServicePolled(String ifAddr, String svcName, org.opennms.netmgt.config.poller.Package ipPkg) {
boolean svcToBePolled = false;
if (ipPkg != null) {
svcToBePolled = PollerConfigFactory.getInstance().isPolled(svcName, ipPkg);
if (!svcToBePolled)
svcToBePolled = PollerConfigFactory.getInstance().isPolled(ifAddr, svcName);
}
return svcToBePolled;
}
private static boolean isServicePolledLocally(String ifAddr, String svcName, org.opennms.netmgt.config.poller.Package ipPkg) {
boolean svcToBePolled = false;
if (ipPkg != null && !ipPkg.getRemote()) {
svcToBePolled = PollerConfigFactory.getInstance().isPolled(svcName, ipPkg);
if (!svcToBePolled)
svcToBePolled = PollerConfigFactory.getInstance().isPolledLocally(ifAddr, svcName);
}
return svcToBePolled;
}
/**
* This method is responsible for updating the status of services for an
* interface during a forced rescan
*
* @param node
* Node entry for the node being rescanned
* @param dbIpIfEntry
* interface entry of the updating interface
* @param dbSupportedServices
* services on the updating interface
*
* @throws SQLException
* if there is a problem updating the snmpInterface table.
*/
private void updateServicesOnForcedRescan(DbNodeEntry node, DbIpInterfaceEntry dbIpIfEntry, DbIfServiceEntry[] dbSupportedServices) throws SQLException {
/*
* Now process previously existing protocols to update polling status.
* Additional checks on forced rescan for existing services go here.
* Specifically, has service been forced managed/unmanaged or has
* polling status changed?
*/
PollerConfig pollerCfgFactory = PollerConfigFactory.getInstance();
CapsdConfig cFactory = CapsdConfigFactory.getInstance();
InetAddress ifaddr = dbIpIfEntry.getIfAddress();
org.opennms.netmgt.config.poller.Package ipPkg = null;
boolean ipToBePolled = false;
final String ifaddrString = str(ifaddr);
ipPkg = ifaddrString == null? null : pollerCfgFactory.getFirstPackageMatch(ifaddrString);
if (ipPkg != null) {
ipToBePolled = true;
}
if (log().isDebugEnabled()) {
log().debug("updateServicesOnForcedRescan: Checking status of existing services on host " + ifaddr);
}
// Get service names from database
java.sql.Connection ctest = null;
ResultSet rs = null;
Map<Integer, String> serviceNames = new HashMap<Integer, String>();
final DBUtils d = new DBUtils(RescanProcessor.class);
try {
ctest = DataSourceFactory.getInstance().getConnection();
d.watch(ctest);
PreparedStatement loadStmt = ctest.prepareStatement(SQL_RETRIEVE_SERVICE_IDS);
d.watch(loadStmt);
// go ahead and load the service table
rs = loadStmt.executeQuery();
d.watch(rs);
while (rs.next()) {
Integer id = new Integer(rs.getInt(1));
String name = rs.getString(2);
serviceNames.put(id, name);
}
} catch (Throwable t) {
log().error("Error reading services table", t);
} finally {
d.cleanUp();
}
for (int i = 0; i < dbSupportedServices.length; i++) {
Integer id = dbSupportedServices[i].getServiceId();
String sn = (serviceNames.get(id)).toString();
DbIfServiceEntry ifSvcEntry = DbIfServiceEntry.get(node.getNodeId(), ifaddr, dbSupportedServices[i].getServiceId());
if (log().isDebugEnabled()) {
log().debug("updateServicesOnForcedRescan: old status for nodeId " + node.getNodeId() + ", ifaddr " + ifaddr + ", serviceId " + dbSupportedServices[i].getServiceId() + " = " + ifSvcEntry.getStatus());
}
// now fill in the entry
boolean svcChangeToActive = false;
boolean svcChangeToNotPolled = false;
boolean svcChangeToForced = false;
if (!cFactory.isAddressUnmanaged(ifaddr)) {
boolean svcToBePolled = false;
if (ipToBePolled) {
if (ipPkg == null) {
ipPkg = pollerCfgFactory.getFirstPackageMatch(ifaddrString);
}
if (ipPkg != null) {
if (log().isDebugEnabled()) {
log().debug("updateServicesOnForcedRescan: Is service to be polled for package = " + ipPkg.getName() + ", service = " + sn);
}
svcToBePolled = pollerCfgFactory.isPolled(sn, ipPkg);
if (!svcToBePolled) {
if (log().isDebugEnabled()) {
log().debug("updateServicesOnForcedRescan: Is service to be polled for ifaddr = " + ifaddrString + ", service = " + sn);
}
svcToBePolled = pollerCfgFactory.isPolled(ifaddrString, sn);
}
if (!svcToBePolled) {
log().debug("updateServicesOnForcedRescan: Service not to be polled");
}
} else {
log().debug("updateServicesOnForcedRescan: No poller package found");
}
} else {
log().debug("updateServicesOnForcedRescan: Service not polled because interface is not polled");
}
if (ifSvcEntry.getStatus() == DbIfServiceEntry.STATUS_FORCED) {
if (svcToBePolled) {
// Do nothing
log().debug("updateServicesOnForcedRescan: status = FORCED. No action taken.");
} else {
// change the status to "N"
ifSvcEntry.updateStatus(DbIfServiceEntry.STATUS_NOT_POLLED);
svcChangeToNotPolled = true;
log().debug("updateServicesOnForcedRescan: status = FORCED. Changed to NOT_POLLED");
}
} else if (ifSvcEntry.getStatus() == DbIfServiceEntry.STATUS_SUSPEND) {
if (svcToBePolled) {
// change the status to "F"
ifSvcEntry.updateStatus(DbIfServiceEntry.STATUS_FORCED);
svcChangeToForced = true;
log().debug("updateServicesOnForcedRescan: status = SUSPEND. Changed to FORCED");
} else {
// change the status to "N"
ifSvcEntry.updateStatus(DbIfServiceEntry.STATUS_NOT_POLLED);
svcChangeToNotPolled = true;
log().debug("updateServicesOnForcedRescan: status = SUSPEND. Changed to NOT_POLLED");
}
} else if (ifSvcEntry.getStatus() == DbIfServiceEntry.STATUS_RESUME) {
if (svcToBePolled) {
// change the status to "A"
ifSvcEntry.updateStatus(DbIfServiceEntry.STATUS_ACTIVE);
svcChangeToActive = true;
log().debug("updateServicesOnForcedRescan: status = RESUME. Changed to ACTIVE");
} else {
// change the status to "N"
ifSvcEntry.updateStatus(DbIfServiceEntry.STATUS_NOT_POLLED);
svcChangeToNotPolled = true;
log().debug("updateServicesOnForcedRescan: status = RESUME. Changed to NOT_POLLED");
}
} else if (svcToBePolled && ifSvcEntry.getStatus() != DbIfServiceEntry.STATUS_ACTIVE) {
// set the status to "A"
ifSvcEntry.updateStatus(DbIfServiceEntry.STATUS_ACTIVE);
svcChangeToActive = true;
log().debug("updateServicesOnForcedRescan: New status = ACTIVE");
} else if (!svcToBePolled && ifSvcEntry.getStatus() == DbIfServiceEntry.STATUS_ACTIVE) {
// set the status to "N"
ifSvcEntry.updateStatus(DbIfServiceEntry.STATUS_NOT_POLLED);
svcChangeToNotPolled = true;
log().debug("updateServicesOnForcedRescan: New status = NOT_POLLED");
} else {
log().debug("updateServicesOnForcedRescan: Status Unchanged");
}
}
if (svcChangeToActive) {
ifSvcEntry.store();
m_eventList.add(createResumePollingServiceEvent(node, dbIpIfEntry, sn));
} else if (svcChangeToNotPolled || svcChangeToForced) {
ifSvcEntry.store();
m_eventList.add(createSuspendPollingServiceEvent(node, dbIpIfEntry, sn));
}
}
}
/**
* This method is responsible for updating the snmpInterface table entry for
* a specific interface.
*
* @param dbc
* Database Connection
* @param node
* Node entry for the node being rescanned
* @param dbIpIfEntry
* interface entry of the updating interface
* @param snmpc
* SNMP collector or null if SNMP not supported.
*
* @throws SQLException
* if there is a problem updating the snmpInterface table.
*/
private void updateSnmpInfo(Connection dbc, DbNodeEntry node,
IfSnmpCollector snmpc, InetAddress ifaddr, int ifIndex)
throws SQLException {
/*
* If SNMP info is available update the snmpInterface table entry with
* anything that has changed.
*/
if (snmpc != null && !snmpc.failed() && ifIndex != -1) {
if (log().isDebugEnabled()) {
log().debug("updateSnmpInfo: updating SNMP interface for "
+ "nodeId/ifIndex="
+ node.getNodeId() + "/" + ifIndex);
}
// Create and load SNMP Interface entry from the database
boolean newSnmpIfTableEntry = false;
DbSnmpInterfaceEntry dbSnmpIfEntry =
DbSnmpInterfaceEntry.get(dbc, node.getNodeId(), ifIndex);
if (dbSnmpIfEntry == null) {
/*
* SNMP Interface not found with this nodeId, create new
* interface
*/
if (log().isDebugEnabled()) {
log().debug("updateSnmpInfo: SNMP interface index " + ifIndex
+ " not in database, creating new interface "
+ "object.");
}
dbSnmpIfEntry = DbSnmpInterfaceEntry.create(node.getNodeId(),
ifIndex);
newSnmpIfTableEntry = true;
}
/*
* Create SNMP interface entry representing latest information
* retrieved for the interface via the collector
*/
DbSnmpInterfaceEntry currSnmpIfEntry =
DbSnmpInterfaceEntry.create(node.getNodeId(), ifIndex);
// Find the ifTable entry for this interface
IfTable ift = snmpc.getIfTable();
IfTableEntry ifte = null;
for (IfTableEntry current : ift) {
// index
Integer sint = current.getIfIndex();
if (sint != null) {
if (ifIndex == sint.intValue()) {
ifte = current;
break;
}
}
}
// Make sure we have a valid IfTableEntry object
if (ifte == null
&& ifIndex == CapsdConfig.LAME_SNMP_HOST_IFINDEX) {
if (log().isDebugEnabled()) {
log().debug("updateSnmpInfo: interface "
+ str(snmpc.getCollectorTargetAddress())
+ " appears to be a lame SNMP host");
}
} else if (ifte != null) {
/*
* IP address and netmask
*
* WARNING: IfSnmpCollector.getIfAddressAndMask() ONLY returns
* the FIRST IP address and mask for a given interface as
* specified in the ipAddrTable.
*/
InetAddress[] aaddrs = snmpc.getIfAddressAndMask(ifIndex);
if (aaddrs == null) {
// disable collection on interface with no ip address by default
currSnmpIfEntry.setCollect("N");
} else {
// mark the interface is collection enable
currSnmpIfEntry.setCollect("C");
// netmask
if (aaddrs[1] != null) {
if (log().isDebugEnabled()) {
log().debug("updateSnmpInfo: interface "
+ str(aaddrs[0])
+ " has netmask: "
+ str(aaddrs[1]));
}
currSnmpIfEntry.setNetmask(aaddrs[1]);
}
}
// type
Integer sint = ifte.getIfType();
currSnmpIfEntry.setType(sint.intValue());
// description
String str = ifte.getIfDescr();
if (log().isDebugEnabled()) {
log().debug("updateSnmpInfo: " + ifaddr
+ " has ifDescription: " + str);
}
if (str != null && str.length() > 0) {
currSnmpIfEntry.setDescription(str);
}
String physAddr = ifte.getPhysAddr();
if (log().isDebugEnabled()) {
log().debug("updateSnmpInfo: " + ifaddr
+ " has phys address: -" + physAddr + "-");
}
if (physAddr != null && physAddr.length() == 12) {
currSnmpIfEntry.setPhysicalAddress(physAddr);
}
// speed
Long speed = snmpc.getInterfaceSpeed(ifIndex);
//set the default speed to 10MB if not retrievable.
currSnmpIfEntry.setSpeed((speed == null
? 10000000L : speed.longValue()));
// admin status
sint = ifte.getIfAdminStatus();
currSnmpIfEntry.setAdminStatus(sint == null ? 0 : sint.intValue());
// oper status
sint = ifte.getIfOperStatus();
currSnmpIfEntry.setOperationalStatus(sint == null ? 0 : sint.intValue());
// name (from interface extensions table)
String ifName = snmpc.getIfName(ifIndex);
if (ifName != null && ifName.length() > 0) {
currSnmpIfEntry.setName(ifName);
}
// alias (from interface extensions table)
String ifAlias = snmpc.getIfAlias(ifIndex);
if (ifAlias != null) {
currSnmpIfEntry.setAlias(ifAlias);
} else {
currSnmpIfEntry.setAlias("");
}
} // end if valid ifTable entry
// Update any fields which have changed
// dbSnmpIfEntry.updateIfIndex(currSnmpIfEntry.getIfIndex());
dbSnmpIfEntry.updateNetmask(currSnmpIfEntry.getNetmask());
dbSnmpIfEntry.updatePhysicalAddress(currSnmpIfEntry.getPhysicalAddress());
dbSnmpIfEntry.updateDescription(currSnmpIfEntry.getDescription());
dbSnmpIfEntry.updateName(currSnmpIfEntry.getName());
dbSnmpIfEntry.updateType(currSnmpIfEntry.getType());
dbSnmpIfEntry.updateSpeed(currSnmpIfEntry.getSpeed());
dbSnmpIfEntry.updateAdminStatus(currSnmpIfEntry.getAdminStatus());
dbSnmpIfEntry.updateOperationalStatus(currSnmpIfEntry.getOperationalStatus());
dbSnmpIfEntry.updateAlias(currSnmpIfEntry.getAlias());
dbSnmpIfEntry.updateCollect(currSnmpIfEntry.getCollect());
/*
* If this is a new interface or if any of the following
* key fields have changed set the m_snmpIfTableChangedFlag
* variable to TRUE. This will potentially trigger an event
* which will cause the poller to reinitialize the primary
* SNMP interface for the node.
*/
// dbSnmpIfEntry.hasIfIndexChanged() ||
if (!m_snmpIfTableChangedFlag && newSnmpIfTableEntry
|| dbSnmpIfEntry.hasTypeChanged()
|| dbSnmpIfEntry.hasNameChanged()
|| dbSnmpIfEntry.hasDescriptionChanged()
|| dbSnmpIfEntry.hasPhysicalAddressChanged()
|| dbSnmpIfEntry.hasAliasChanged()) {
m_snmpIfTableChangedFlag = true;
}
// Update the database
dbSnmpIfEntry.store(dbc);
// end if complete snmp info available
} else if (snmpc != null && snmpc.hasIpAddrTable() && ifIndex != -1) {
if (log().isDebugEnabled()) {
log().debug("updateSnmpInfo: updating SNMP interface for "
+ "nodeId/ifIndex/ipAddr="
+ node.getNodeId() + "/" + ifIndex + "/" + ifaddr
+ " based on ipAddrTable only - No ifTable "
+ "available");
}
// Create and load SNMP Interface entry from the database
DbSnmpInterfaceEntry dbSnmpIfEntry =
DbSnmpInterfaceEntry.get(dbc, node.getNodeId(), ifIndex);
if (dbSnmpIfEntry == null) {
/*
* SNMP Interface not found with this nodeId, create new
* interface
*/
if (log().isDebugEnabled()) {
log().debug("updateSnmpInfo: SNMP interface index " + ifIndex
+ " not in database, creating new interface "
+ "object.");
}
dbSnmpIfEntry = DbSnmpInterfaceEntry.create(node.getNodeId(),
ifIndex);
}
/*
* Create SNMP interface entry representing latest information
* retrieved for the interface via the collector
*/
DbSnmpInterfaceEntry.create(node.getNodeId(), ifIndex);
// Update the database
dbSnmpIfEntry.store(dbc);
// end if partial snmp info available
} else if (snmpc != null) {
// allow for lame snmp hosts with no ipAddrTable
ifIndex = CapsdConfig.LAME_SNMP_HOST_IFINDEX;
if (log().isDebugEnabled()) {
log().debug("updateSnmpInfo: updating SNMP interface for "
+ "nodeId/ipAddr=" + node.getNodeId() + "/" + ifaddr
+ " based on ip address only - No ipAddrTable "
+ "available");
}
// Create and load SNMP Interface entry from the database
DbSnmpInterfaceEntry dbSnmpIfEntry =
DbSnmpInterfaceEntry.get(dbc, node.getNodeId(), ifIndex);
if (dbSnmpIfEntry == null) {
/*
* SNMP Interface not found with this nodeId, create new
* interface
*/
if (log().isDebugEnabled()) {
log().debug("updateSnmpInfo: SNMP interface index " + ifIndex
+ " not in database, creating new interface "
+ "object.");
}
dbSnmpIfEntry = DbSnmpInterfaceEntry.create(node.getNodeId(),
ifIndex);
}
/*
* Create SNMP interface entry representing latest information
* retrieved for the interface via the collector
*/
DbSnmpInterfaceEntry.create(node.getNodeId(), ifIndex);
// Update the database
dbSnmpIfEntry.store(dbc);
}
}
/**
* This method is responsible for reparenting an interface's database table
* entries under its new node identifier. The following tables are updated:
*
* ipInterface snmpInterface ifServices
*
* @param dbc
* Database connection
* @param ifAddr
* Interface to be reparented.
* @param newNodeId
* Interface's new node identifier
* @param oldNodeId
* Interfaces' old node identifier
*
* @throws SQLException
* if a database error occurs during reparenting.
*/
private static void reparentInterface(Connection dbc, InetAddress ifAddr, int ifIndex, int newNodeId, int oldNodeId) throws SQLException {
String ipaddr = str(ifAddr);
final DBUtils d = new DBUtils(RescanProcessor.class);
try {
PreparedStatement ifLookupStmt = dbc.prepareStatement(SQL_DB_REPARENT_IP_INTERFACE_LOOKUP);
d.watch(ifLookupStmt);
PreparedStatement ifDeleteStmt = dbc.prepareStatement(SQL_DB_REPARENT_IP_INTERFACE_DELETE);
d.watch(ifDeleteStmt);
PreparedStatement ipInterfaceStmt = dbc.prepareStatement(SQL_DB_REPARENT_IP_INTERFACE);
d.watch(ipInterfaceStmt);
PreparedStatement snmpIfLookupStmt = dbc.prepareStatement(SQL_DB_REPARENT_SNMP_IF_LOOKUP);
d.watch(snmpIfLookupStmt);
PreparedStatement snmpIfDeleteStmt = dbc.prepareStatement(SQL_DB_REPARENT_SNMP_IF_DELETE);
d.watch(snmpIfDeleteStmt);
PreparedStatement snmpInterfaceStmt = dbc.prepareStatement(SQL_DB_REPARENT_SNMP_INTERFACE);
d.watch(snmpInterfaceStmt);
PreparedStatement ifServicesLookupStmt = dbc.prepareStatement(SQL_DB_REPARENT_IF_SERVICES_LOOKUP);
d.watch(ifServicesLookupStmt);
PreparedStatement ifServicesDeleteStmt = dbc.prepareStatement(SQL_DB_REPARENT_IF_SERVICES_DELETE);
d.watch(ifServicesDeleteStmt);
PreparedStatement ifServicesStmt = dbc.prepareStatement(SQL_DB_REPARENT_IF_SERVICES);
d.watch(ifServicesStmt);
if (log().isDebugEnabled()) {
log().debug("reparentInterface: reparenting address/ifIndex/nodeID: " + ipaddr + "/" + ifIndex + "/" + newNodeId);
}
/*
* SNMP interface
*
* NOTE: Only reparent SNMP interfaces if we have valid ifIndex
*/
if (ifIndex < 1) {
log().debug("reparentInterface: don't have a valid ifIndex, skipping snmpInterface table reparenting.");
} else {
/*
* NOTE: Now that the snmpInterface table is uniquely keyed
* by nodeId and ifIndex we must only reparent the
* old entry if there isn't already an entry with
* the same nodeid/ifindex pairing. If it can't
* be reparented it will be deleted.
*/
/*
* Look for matching nodeid/ifindex for the entry to be
* reparented
*/
boolean alreadyExists = false;
snmpIfLookupStmt.setInt(1, newNodeId);
snmpIfLookupStmt.setInt(2, ifIndex);
ResultSet rs = snmpIfLookupStmt.executeQuery();
d.watch(rs);
if (rs.next()) {
/*
* Looks like we got a match so just delete
* the entry from the old node
*/
if (log().isDebugEnabled()) {
log().debug("reparentInterface: interface with ifindex " + ifIndex + " already exists under new node " + newNodeId + " in snmpinterface table, deleting from under old node " + oldNodeId);
}
alreadyExists = true;
snmpIfDeleteStmt.setInt(1, oldNodeId);
snmpIfDeleteStmt.setInt(2, ifIndex);
snmpIfDeleteStmt.executeUpdate();
}
if (alreadyExists == false) {
/*
* Update the 'snmpinterface' table entry so that this
* interface's nodeID is set to the value of reparentNodeID
*/
if (log().isDebugEnabled()) {
log().debug("reparentInterface: interface with ifindex " + ifIndex + " does not yet exist under new node " + newNodeId + " in snmpinterface table, reparenting.");
}
snmpInterfaceStmt.setInt(1, newNodeId);
snmpInterfaceStmt.setInt(2, oldNodeId);
snmpInterfaceStmt.setInt(3, ifIndex);
// execute and log
snmpInterfaceStmt.executeUpdate();
}
}
// Look for matching nodeid/ifindex for the entry to be reparented
boolean ifAlreadyExists = false;
ifLookupStmt.setInt(1, newNodeId);
ifLookupStmt.setString(2, ipaddr);
ResultSet rs = ifLookupStmt.executeQuery();
d.watch(rs);
if (rs.next()) {
/*
* Looks like we got a match so just delete
* the entry from the old node
*/
if (log().isDebugEnabled()) {
log().debug("reparentInterface: interface with ifindex " + ifIndex + " already exists under new node " + newNodeId + " in ipinterface table, deleting from under old node " + oldNodeId);
}
ifAlreadyExists = true;
ifDeleteStmt.setInt(1, oldNodeId);
ifDeleteStmt.setString(2, ipaddr);
ifDeleteStmt.executeUpdate();
}
if (ifAlreadyExists == false) {
/*
* Update the 'ipinterface' table entry so that this
* interface's nodeID is set to the value of reparentNodeID
*/
if (log().isDebugEnabled()) {
log().debug("reparentInterface: interface with ifindex " + ifIndex + " does not yet exist under new node " + newNodeId + " in ipinterface table, reparenting.");
}
ipInterfaceStmt.setInt(1, newNodeId);
ipInterfaceStmt.setInt(2, oldNodeId);
ipInterfaceStmt.setString(3, ipaddr);
// execute and log
ipInterfaceStmt.executeUpdate();
}
// Look for matching nodeid/ifindex for the entry to be reparented
boolean ifsAlreadyExists = false;
ifServicesLookupStmt.setInt(1, newNodeId);
ifServicesLookupStmt.setString(2, ipaddr);
ifServicesLookupStmt.setInt(3, ifIndex);
rs = ifServicesLookupStmt.executeQuery();
d.watch(rs);
if (rs.next()) {
/*
* Looks like we got a match so just delete
* the entry from the old node
*/
if (log().isDebugEnabled()) {
log().debug("reparentInterface: interface with ifindex " + ifIndex + " already exists under new node " + newNodeId + " in ifservices table, deleting from under old node " + oldNodeId);
}
ifsAlreadyExists = true;
ifServicesDeleteStmt.setInt(1, oldNodeId);
ifServicesDeleteStmt.setString(2, ipaddr);
ifServicesDeleteStmt.executeUpdate();
}
if (ifsAlreadyExists == false) {
/*
* Update the 'snmpinterface' table entry so that this
* interface's nodeID is set to the value of reparentNodeID
*/
if (log().isDebugEnabled()) {
log().debug("reparentInterface: interface with ifindex " + ifIndex + " does not yet exist under new node " + newNodeId + " in ifservices table, reparenting.");
}
/*
* Update the 'nodeID' field of all 'ifservices' table entries
* for the reparented interfaces.
*/
ifServicesStmt.setInt(1, newNodeId);
ifServicesStmt.setInt(2, oldNodeId);
ifServicesStmt.setString(3, ipaddr);
// execute and log
ifServicesStmt.executeUpdate();
}
if (log().isDebugEnabled()) {
log().debug("reparentInterface: reparented " + ipaddr + " : ifIndex: " + ifIndex + " : oldNodeID: " + oldNodeId + " newNodeID: " + newNodeId);
}
} catch (SQLException sqlE) {
log().error("SQLException while reparenting addr/ifindex/nodeid " + ipaddr + "/" + ifIndex + "/" + oldNodeId);
throw sqlE;
} finally {
d.cleanUp();
}
}
/**
* Builds a list of InetAddress objects representing each of the interfaces
* from the collector map object which support SNMP and have a valid ifIndex
* and have an IfType of loopback.
*
* This is part of a feature to choose a non 127.*.*.* loopback address as
* the primary SNMP interface.
*
* @param collectorMap
* Map of IfCollector objects containing data collected from all
* of the node's interfaces.
* @param snmpc
* Reference to SNMP collection object
*
* @return List of InetAddress objects.
*/
private static List<InetAddress> buildLBSnmpAddressList(Map<String, IfCollector> collectorMap, IfSnmpCollector snmpc) {
List<InetAddress> addresses = new ArrayList<InetAddress>();
// Verify that we have SNMP info
if (snmpc == null) {
log().debug("buildLBSnmpAddressList: no SNMP info available...");
return addresses;
}
if (!snmpc.hasIfTable()) {
log().debug("buildLBSnmpAddressList: no SNMP ifTable available...");
return addresses;
}
/*
* To be eligible to be the primary SNMP interface for a node:
*
* 1. The interface must support SNMP
* 2. The interface must have a valid ifIndex.
*/
Collection<IfCollector> values = collectorMap.values();
Iterator<IfCollector> iter = values.iterator();
while (iter.hasNext()) {
IfCollector ifc = iter.next();
// Add eligible target.
InetAddress ifaddr = ifc.getTarget();
if (addresses.contains(ifaddr) == false) {
if (SuspectEventProcessor.supportsSnmp(ifc.getSupportedProtocols()) && SuspectEventProcessor.hasIfIndex(ifaddr, snmpc) && SuspectEventProcessor.getIfType(ifaddr, snmpc) == 24) {
if (log().isDebugEnabled()) {
log().debug("buildLBSnmpAddressList: adding target interface " + str(ifaddr) + " temporarily marked as primary!");
}
addresses.add(ifaddr);
}
}
// Now go through list of sub-targets
if (ifc.hasAdditionalTargets()) {
Map<InetAddress, List<SupportedProtocol>> subTargets = ifc.getAdditionalTargets();
for(InetAddress xifaddr : subTargets.keySet()) {
if (addresses.contains(xifaddr) == false) {
if (SuspectEventProcessor.supportsSnmp(subTargets.get(xifaddr)) && SuspectEventProcessor.hasIfIndex(xifaddr, snmpc) && SuspectEventProcessor.getIfType(xifaddr, snmpc) == 24) {
if (log().isDebugEnabled()) {
log().debug("buildLBSnmpAddressList: adding subtarget interface " + str(xifaddr) + " temporarily marked as primary!");
}
addresses.add(xifaddr);
}
}
}
}
}
return addresses;
}
/**
* Builds a list of InetAddress objects representing each of the interfaces
* from the collector map object which support SNMP and have a valid
* ifIndex.
*
* @param collectorMap
* Map of IfCollector objects containing data collected from all
* of the node's interfaces.
* @param snmpc
* Reference to SNMP collection object
*
* @return List of InetAddress objects.
*/
private static List<InetAddress> buildSnmpAddressList(Map<String, IfCollector> collectorMap, IfSnmpCollector snmpc) {
List<InetAddress> addresses = new ArrayList<InetAddress>();
// Verify that we have SNMP info
if (snmpc == null) {
log().debug("buildSnmpAddressList: no SNMP info available...");
return addresses;
}
/*
* To be eligible to be the primary SNMP interface for a node:
*
* 1. The interface must support SNMP
* 2. The interface must have a valid ifIndex.
*/
Collection<IfCollector> values = collectorMap.values();
Iterator<IfCollector> iter = values.iterator();
while (iter.hasNext()) {
IfCollector ifc = iter.next();
// Add eligible target.
InetAddress ifaddr = ifc.getTarget();
if (addresses.contains(ifaddr) == false) {
if (SuspectEventProcessor.supportsSnmp(ifc.getSupportedProtocols()) && SuspectEventProcessor.hasIfIndex(ifaddr, snmpc)) {
if (log().isDebugEnabled()) {
log().debug("buildSnmpAddressList: adding target interface " + str(ifaddr) + " temporarily marked as primary!");
}
addresses.add(ifaddr);
}
}
// Now go through list of sub-targets
if (ifc.hasAdditionalTargets()) {
Map<InetAddress, List<SupportedProtocol>> subTargets = ifc.getAdditionalTargets();
for(InetAddress xifaddr : subTargets.keySet()) {
// Add eligible subtargets.
if (addresses.contains(xifaddr) == false) {
if (SuspectEventProcessor.supportsSnmp(subTargets.get(xifaddr)) && SuspectEventProcessor.hasIfIndex(xifaddr, snmpc)) {
if (log().isDebugEnabled()) {
log().debug("buildSnmpAddressList: adding subtarget interface " + str(xifaddr) + " temporarily marked as primary!");
}
addresses.add(xifaddr);
}
}
}
}
}
return addresses;
}
/**
* This method is responsible for determining the primary IP interface for
* the node being rescanned.
*
* @param collectorMap
* Map of IfCollector objects containing data collected from all
* of the node's interfaces.
*
* @return InetAddress The primary IP interface for the node or null if a
* primary interface for the node could not be determined.
*/
private static InetAddress determinePrimaryIpInterface(Map<String, IfCollector> collectorMap) {
Collection<IfCollector> values = collectorMap.values();
Iterator<IfCollector> iter = values.iterator();
InetAddress primaryIf = null;
while (iter.hasNext()) {
IfCollector ifc = iter.next();
InetAddress currIf = ifc.getTarget();
if (primaryIf == null) {
primaryIf = currIf;
continue;
} else {
// Test the target interface of the collector first.
primaryIf = SuspectEventProcessor.compareAndSelectPrimary(currIf, primaryIf);
// Now test each of the collected subtargets
if (ifc.hasAdditionalTargets()) {
Map<InetAddress, List<SupportedProtocol>> subTargets = ifc.getAdditionalTargets();
Iterator<InetAddress> siter = subTargets.keySet().iterator();
while (siter.hasNext()) {
currIf = siter.next();
primaryIf = SuspectEventProcessor.compareAndSelectPrimary(currIf, primaryIf);
}
}
}
}
if (log().isDebugEnabled()) {
if (primaryIf != null) {
log().debug("determinePrimaryIpInterface: selected primary interface: " + str(primaryIf));
} else {
log().debug("determinePrimaryIpInterface: no primary interface found");
}
}
return primaryIf;
}
/**
* Primarily, this method is responsible for assigning the node's nodeLabel
* value using information collected from the node's various interfaces.
* Additionally, if the node talks NetBIOS/SMB, then the node's NetBIOS name
* and operating system fields are assigned.
*
* @param collectorMap
* Map of IfCollector objects, one per interface.
* @param dbNodeEntry
* Node entry, as it exists in the database.
* @param currNodeEntry
* Current node entry, as collected during the current rescan.
* @param currPrimarySnmpIf
* Primary SNMP interface, as determined from the collection
* retrieved during the current rescan.
*/
private static void setNodeLabelAndSmbInfo(Map<String, IfCollector> collectorMap, DbNodeEntry dbNodeEntry, DbNodeEntry currNodeEntry, InetAddress currPrimarySnmpIf) {
boolean labelSet = false;
/*
* We are going to change the order in which labels are assigned.
* First, we check DNS - the hostname of the primary interface.
* Then we check SMB - next SNMP sysName - and finally IP address
* This is different then in 1.0 - when SMB came first.
*/
InetAddress primaryIf = null;
if (!labelSet) {
/*
* If no label is set, attempt to get the hostname for the primary
* SNMP interface.
* Note: this was wrong prior to 1.0.1 - the method
* determinePrimaryIpInterface
* would return the lowest numbered interface, not necessarily the
* primary SNMP interface.
*/
if (currPrimarySnmpIf != null) {
primaryIf = currPrimarySnmpIf;
} else {
primaryIf = determinePrimaryIpInterface(collectorMap);
}
if (primaryIf == null) {
log().error("setNodeLabelAndSmbInfo: failed to find primary interface...");
} else {
String hostName = primaryIf.getHostName();
if (!hostName.equals(str(primaryIf))) {
labelSet = true;
currNodeEntry.setLabel(hostName);
currNodeEntry.setLabelSource(DbNodeEntry.LABEL_SOURCE_HOSTNAME);
}
}
}
IfSmbCollector savedSmbcRef = null;
// Does the node entry in database have a NetBIOS name?
if (dbNodeEntry.getNetBIOSName() != null) {
/*
* Yes it does, so search through collected info for all
* interfaces and see if any have a NetBIOS name
* which matches the existing one in the database
*/
Collection<IfCollector> values = collectorMap.values();
Iterator<IfCollector> iter = values.iterator();
while (iter.hasNext() && !labelSet) {
IfCollector ifc = iter.next();
IfSmbCollector smbc = ifc.getSmbCollector();
if (smbc != null) {
if (smbc.getNbtName() != null) {
/*
* Save reference to first IfSmbCollector object
* for future use.
*/
savedSmbcRef = smbc;
String netbiosName = smbc.getNbtName().toUpperCase();
if (netbiosName.equals(dbNodeEntry.getNetBIOSName())) {
// Found a match.
labelSet = true;
currNodeEntry.setLabel(netbiosName);
currNodeEntry.setLabelSource(DbNodeEntry.LABEL_SOURCE_NETBIOS);
currNodeEntry.setNetBIOSName(netbiosName);
if (smbc.getDomainName() != null) {
currNodeEntry.setDomainName(smbc.getDomainName());
}
}
}
}
}
} else {
/*
* No it does not, attempt to find an interface
* collector that does have a NetBIOS name and
* save a reference to that collector
*/
Collection<IfCollector> values = collectorMap.values();
Iterator<IfCollector> iter = values.iterator();
while (iter.hasNext()) {
IfCollector ifc = iter.next();
IfSmbCollector smbc = ifc.getSmbCollector();
if (smbc != null && smbc.getNbtName() != null) {
savedSmbcRef = smbc;
}
}
}
/*
* If node label has not yet been set and SMB info is available
* use that info to set the node label and NetBIOS name
*/
if (!labelSet && savedSmbcRef != null) {
labelSet = true;
currNodeEntry.setLabel(savedSmbcRef.getNbtName());
currNodeEntry.setLabelSource(DbNodeEntry.LABEL_SOURCE_NETBIOS);
currNodeEntry.setNetBIOSName(currNodeEntry.getLabel());
if (savedSmbcRef.getDomainName() != null) {
currNodeEntry.setDomainName(savedSmbcRef.getDomainName());
}
}
/*
* If we get this far no IP hostname or SMB info was available. Next we
* want to use MIB-II sysName for the node label. The primary SNMP
* interface has already been determined so use it if available.
*/
if (!labelSet && currPrimarySnmpIf != null) {
/*
* We prefer to use the collector for the primary SNMP interface
* however a collector for the primary SNMP interface may not exist
* in the map if a node has only recently had SNMP support enabled
* or if the new primary SNMP interface was only recently added to
* the node. At any rate if it exists use it, if not use the
* first collector which supports SNMP.
*/
final String currPrimarySnmpAddress = str(currPrimarySnmpIf);
IfCollector ifc = currPrimarySnmpAddress == null? null : collectorMap.get(currPrimarySnmpAddress);
if (ifc == null) {
Collection<IfCollector> collectors = collectorMap.values();
Iterator<IfCollector> iter = collectors.iterator();
while (iter.hasNext()) {
ifc = iter.next();
if (ifc.getSnmpCollector() != null) {
break;
}
}
}
// Sanity check
if (ifc == null || ifc.getSnmpCollector() == null) {
log().warn("setNodeLabelAndSmbInfo: primary SNMP interface set to " + currPrimarySnmpAddress + " but no SNMP collector found.");
} else {
IfSnmpCollector snmpc = ifc.getSnmpCollector();
SystemGroup sysgrp = snmpc.getSystemGroup();
String str = sysgrp.getSysName();
if (str != null && str.length() > 0) {
labelSet = true;
currNodeEntry.setLabel(str);
currNodeEntry.setLabelSource(DbNodeEntry.LABEL_SOURCE_SYSNAME);
}
}
}
if (!labelSet) {
/*
* If we get this far no SNMP info was available so we will default
* to the IP address of the primary interface.
*/
if (primaryIf != null) {
currNodeEntry.setLabel(str(primaryIf));
currNodeEntry.setLabelSource(DbNodeEntry.LABEL_SOURCE_ADDRESS);
} else {
/*
* If all else fails, just use the current values from
* the database.
*/
currNodeEntry.setLabel(dbNodeEntry.getLabel());
currNodeEntry.setLabelSource(dbNodeEntry.getLabelSource());
}
}
}
/**
* Utility method used to determine if the specified node has been marked as
* deleted in the node table.
*
* @param dbc
* Database connection.
* @param nodeId
* Node identifier to check
*
* @return TRUE if node has been marked as deleted, FALSE otherwise.
*/
private static boolean isNodeDeleted(Connection dbc, int nodeId) throws SQLException {
boolean nodeDeleted = false;
/*
* Prepare & execute the SQL statement to retrieve the 'nodetype' field
* from the node table for the specified nodeid.
*/
PreparedStatement stmt = null;
final DBUtils d = new DBUtils(RescanProcessor.class);
try {
stmt = dbc.prepareStatement(SQL_DB_RETRIEVE_NODE_TYPE);
d.watch(stmt);
stmt.setInt(1, nodeId);
ResultSet rs = stmt.executeQuery();
d.watch(rs);
rs.next();
String nodeTypeStr = rs.getString(1);
if (!rs.wasNull()) {
char nodeType = nodeTypeStr.charAt(0);
if (nodeType == DbNodeEntry.NODE_TYPE_DELETED) {
nodeDeleted = true;
}
}
} finally {
d.cleanUp();
}
return nodeDeleted;
}
/**
* This method is used to verify if each interface on a node stored in the
* database is in the specified SNMP data collection.
*
* @param dbInterfaces
* the ipInterfaces on a node stored in the database
* @param snmpc
* IfSnmpCollector object containing SNMP collected ipAddrTable
* information.
*
* @return True if each ipInterface is contained in the ipAddrTable of the
* specified SNMP collection.
*
*/
private static boolean areDbInterfacesInSnmpCollection(DbIpInterfaceEntry[] dbInterfaces, IfSnmpCollector snmpc) {
// Sanity check...null parms?
if (dbInterfaces == null || snmpc == null) {
log().error("areDbInterfacesInSnmpCollection: empty dbInterfaces or IfSnmpCollector.");
return false;
}
// SNMP collection successful?
if (!snmpc.hasIpAddrTable()) {
log().error("areDbInterfacesInSnmpCollection: SNMP Collector failed.");
return false;
}
// Verify that SNMP collection contains ipAddrTable entries
IpAddrTable ipAddrTable = null;
if (snmpc.hasIpAddrTable()) {
ipAddrTable = snmpc.getIpAddrTable();
}
if (ipAddrTable == null) {
log().error("areDbInterfacesInSnmpCollection: null ipAddrTable in the SNMP collection");
return false;
}
List<InetAddress> ipAddrList = ipAddrTable.getIpAddresses();
/*
* Loop through the interface table entries until there are no more
* entries or we've found a match
*/
for (final DbIpInterfaceEntry dbInterface : dbInterfaces) {
InetAddress ipaddr = dbInterface.getIfAddress();
// Skip non-IP or loopback interfaces
final String ipaddrString = str(ipaddr);
if (ipaddrString == null || ipaddrString.equals("0.0.0.0") || ipaddr.isLoopbackAddress()) {
continue;
}
boolean found = false;
for (final InetAddress addr : ipAddrList) {
// Skip non-IP or loopback interfaces
final String addrString = str(addr);
if (addrString == null || addrString.equals("0.0.0.0") || addr.isLoopbackAddress()) {
continue;
}
if (ipaddrString.equals(addrString)) {
found = true;
if (log().isDebugEnabled()) {
log().debug("areDbInterfacesInSnmpCollection: found match for ipaddress: " + ipaddrString);
}
break;
}
}
if (!found) {
if (log().isDebugEnabled()) {
log().debug("areDbInterfacesInSnmpCollection: ipaddress : " + ipaddrString + " not in the SNMP collection. SNMP collection may not be usable.");
}
return false;
}
}
return true;
}
/**
* This is where all the work of the class is done.
*/
public void run() {
// perform rescan of the node
DbNodeEntry dbNodeEntry = getNode();
if (dbNodeEntry == null) {
return;
}
if (dbNodeEntry.getForeignSource() != null) {
log().info("Skipping rescan of node "+getNodeId()+" since it was imported with foreign source "+dbNodeEntry.getForeignSource());
return;
}
if (log().isDebugEnabled()) {
log().debug("start rescanning node: " + getNodeId());
}
DbIpInterfaceEntry[] dbInterfaces = getInterfaces(dbNodeEntry);
if (dbInterfaces == null) {
log().debug("no interfaces found in the database to rescan for node: "
+ getNodeId());
return;
}
// this indicates whether or not we found an iface the responds to snmp
boolean doesSnmp = true;
IpAddrTable ipAddTable = null;
List<InetAddress> prevAddrList = null;
boolean snmpcAgree = false;
boolean gotSnmpc = false;
Map<String, IfCollector> collectorMap =
new HashMap<String, IfCollector>();
Map<String, IfCollector> nonSnmpCollectorMap =
new HashMap<String, IfCollector>();
Set<InetAddress> probedAddrs = new HashSet<InetAddress>();
boolean gotSnmpCollection = false;
DbIpInterfaceEntry oldPrimarySnmpInterface =
DbNodeEntry.getPrimarySnmpInterface(dbInterfaces);
if (oldPrimarySnmpInterface != null) {
gotSnmpCollection =
scanPrimarySnmpInterface(oldPrimarySnmpInterface, collectorMap,
probedAddrs);
}
if (!gotSnmpCollection) {
/*
* Run collector for each retrieved interface and add result
* to a collector map.
*/
for (int i = 0; i < dbInterfaces.length; i++) {
log().info("run: Running collector for interface "+i+" of "+dbInterfaces.length);
final InetAddress ifaddr = dbInterfaces[i].getIfAddress();
final String ifaddrString = str(ifaddr);
/*
* collect the information from the interface.
* NOTE: skip '127.*.*.*' and '0.0.0.0' addresses.
*/
if (!scannableInterface(dbInterfaces, ifaddr)) {
log().debug("run: skipping scan of address: "+ifaddrString);
continue;
}
if (ifaddrString == null) {
log().debug("run: unable to scan inet address: " + ifaddr);
continue;
}
if (log().isDebugEnabled()) {
log().debug("running collection for " + ifaddrString);
}
IfCollector collector = new IfCollector(m_pluginManager, ifaddr, true, probedAddrs);
collector.run();
IfSnmpCollector snmpc = collector.getSnmpCollector();
if (snmpc != null) {
gotSnmpc = true;
}
if (snmpc != null && snmpc.hasIpAddrTable()
&& snmpc.getIfIndex(snmpc.getCollectorTargetAddress()) != -1) {
if (areDbInterfacesInSnmpCollection(dbInterfaces, snmpc)) {
collectorMap.put(ifaddrString, collector);
gotSnmpCollection = true;
if (log().isDebugEnabled()) {
log().debug("SNMP data collected via "
+ ifaddrString);
log().debug("Adding " + ifaddrString
+ " to collectorMap for node: "
+ getNodeId());
}
snmpcAgree = false;
break;
} else if (ipAddTable == null) {
snmpcAgree = true;
collectorMap.put(ifaddrString, collector);
ipAddTable = snmpc.getIpAddrTable();
prevAddrList = ipAddTable.getIpAddresses();
if (log().isDebugEnabled()) {
log().debug("SNMP data collected via "
+ ifaddrString
+ " does not agree with database. "
+ "Tentatively adding to the "
+ "collectorMap and continuing");
for(InetAddress a : prevAddrList) {
log().debug("IP address in list = " + a);
}
}
} else if (ipAddTable != null && snmpcAgree == true) {
ipAddTable = snmpc.getIpAddrTable();
List<InetAddress> addrList = ipAddTable.getIpAddresses();
boolean listMatch = true;
String jstring = null;
String kstring = null;
Iterator<InetAddress> j = prevAddrList.iterator();
Iterator<InetAddress> k = addrList.iterator();
while (j.hasNext()) {
jstring = j.next().toString();
if (k.hasNext()) {
kstring = k.next().toString();
if (jstring.equals(kstring)) {
if (log().isDebugEnabled()) {
log().debug(jstring + " = " + kstring);
}
} else {
if (log().isDebugEnabled()) {
log().debug(jstring + " != " + kstring);
}
listMatch = false;
}
} else {
listMatch = false;
}
}
if (k.hasNext()) {
listMatch = false;
}
if (listMatch) {
log().debug("Current and previous address lists match");
} else {
log().debug("Current and previous address lists "
+ "DO NOT match");
snmpcAgree = false;
}
collector.deleteSnmpCollector();
}
if (snmpcAgree == false) {
if (log().isDebugEnabled()) {
log().debug("SNMP data collected via "
+ ifaddrString
+ " does not agree with database or with "
+ "other interface(s) on this node.");
}
}
} else {
/*
* Build a non-SNMP collectorMap, skipping 127.*.*.*
* and 0.0.0.0
*/
nonSnmpCollectorMap.put(ifaddrString, collector);
if (log().isDebugEnabled()) {
log().debug("Adding " + ifaddrString
+ " to nonSnmpCollectorMap for node: "
+ getNodeId());
}
}
}
}
if (!gotSnmpCollection && snmpcAgree == false) {
/*
* We didn't get a collection from a primary snmp interface,
* and we didn't get a collection that agrees with the db, and
* multiple interface collections don't agree with each other.
* First check for lame SNMP host, otherwise use the
* nonSnmpCollectorMap and set doesSnmp = false
*/
collectorMap = nonSnmpCollectorMap;
if (nonSnmpCollectorMap.size() == 1 && gotSnmpc) {
doesSnmp = true;
if (log().isDebugEnabled()) {
log().debug("node " + getNodeId()
+ " appears to be a lame SNMP host... "
+ "Proceeding");
}
} else {
doesSnmp = false;
if (log().isDebugEnabled()) {
if (gotSnmpc == false) {
log().debug("Could not collect SNMP data for node: "
+ getNodeId());
} else {
log().debug("Not using SNMP data for node: "
+ getNodeId() + ". "
+ "Collection does not agree with database.");
}
}
}
} else if (snmpcAgree == true) {
/*
* We didn't get a collection from a primary snmp interface,
* and we didn't get a collection that agrees with the db, but
* all collections we DID get agree with each other.
* May want to create an event here
*/
if (log().isDebugEnabled()) {
log().debug("SNMP collection for node: "
+ getNodeId()
+ " does not agree with database, but there is no "
+ "conflict among the interfaces on this node which "
+ "respond to SNMP. Proceeding...");
}
m_eventList.add(createSnmpConflictsWithDbEvent(dbNodeEntry));
}
// Update the database
Date now = null;
Connection dbc = null;
boolean updateCompleted = false;
try {
/*
* Synchronize on the Capsd sync lock so we can check if
* the interface is already in the database and perform
* the necessary inserts in one atomic operation
*
* The SuspectEventProcessor class is also synchronizing on this
* lock prior to performing database inserts or updates.
*/
log().debug("Waiting for capsd dbLock to process "
+ getNodeId());
synchronized (Capsd.getDbSyncLock()) {
log().debug("Got capsd dbLock. processing "
+ getNodeId());
// Get database connection
dbc = DataSourceFactory.getInstance().getConnection();
/*
* There is a slight possibility that the node being rescanned
* has been deleted (due to reparenting) by another thread
* between the time this rescan was started and the database
* sync lock was grabbed. Verify that the current nodeid is
* still valid (ie, not deleted) before continuing.
*/
if (!isNodeDeleted(dbc, getNodeId())) {
// Update interface information
now = new Date();
updateInterfaces(dbc, now, dbNodeEntry, collectorMap,
doesSnmp);
if (doesSnmp) {
InetAddress oldPriIf = null;
if (oldPrimarySnmpInterface != null) {
oldPriIf = oldPrimarySnmpInterface.getIfAddress();
}
InetAddress newSnmpPrimaryIf =
updatePrimarySnmpInterface(dbc, dbNodeEntry,
collectorMap, oldPriIf);
updateNode(dbc, now, dbNodeEntry, newSnmpPrimaryIf,
dbInterfaces, collectorMap);
}
updateCompleted = true;
m_eventList.add(createRescanCompletedEvent(dbNodeEntry));
}
}
} catch (Throwable t) {
log().error("Error updating records for node ID " + getNodeId() + ": " + t, t);
} finally {
// Finished with the database connection, close it.
try {
if (dbc != null) {
dbc.close();
}
} catch (SQLException e) {
log().error("Error closing connection: " + e, e);
}
// Remove the node we just scanned from the tracker set
synchronized (m_queuedRescanTracker) {
m_queuedRescanTracker.remove(getNodeId());
}
}
// Send events associcatd with the rescan
if (updateCompleted) {
// Send all events created during rescan process to eventd
for (Event event : m_eventList) {
try {
EventIpcManagerFactory.getIpcManager().sendNow(event);
} catch (Throwable t) {
log().warn("run: unexpected throwable exception caught "
+ "while sending event: " + t, t);
}
}
}
if (log().isDebugEnabled()) {
log().debug((m_forceRescan ? "Forced r" : "R") + "escan "
+ "for node w/ nodeid " + getNodeId()
+ " completed.");
}
}
/**
* <p>scannableInterface</p>
*
* @param dbInterfaces an array of {@link org.opennms.netmgt.capsd.DbIpInterfaceEntry} objects.
* @param ifaddr a {@link java.net.InetAddress} object.
* @return a boolean.
*/
protected static boolean scannableInterface(final DbIpInterfaceEntry[] dbInterfaces, final InetAddress ifaddr) {
final String ifaddrString = str(ifaddr);
if (ifaddrString == null) return false;
final boolean localHostAddress = (ifaddr.isLoopbackAddress() && dbInterfaces.length > 1);
final boolean nonIpAddress = ifaddrString.equals("0.0.0.0");
final boolean scannable = !localHostAddress && !nonIpAddress;
return scannable;
}
private int getNodeId() {
return m_nodeId;
}
private boolean scanPrimarySnmpInterface(DbIpInterfaceEntry oldPrimarySnmpInterface, Map<String, IfCollector> collectorMap, Set<InetAddress> probedAddrs) {
boolean gotSnmpCollection = false;
/*
* Run collector for DB primary snmp interface and add result
* to a collector map.
*/
final InetAddress ifaddr = oldPrimarySnmpInterface.getIfAddress();
final String ifaddrString = str(ifaddr);
if (ifaddrString == null) {
log().info("old primary SNMP interface has an invalid address: " + ifaddr);
return false;
}
if (log().isDebugEnabled()) {
log().debug("running collection for DB primary SNMP interface " + ifaddrString);
}
IfCollector collector = new IfCollector(m_pluginManager, ifaddr, true, probedAddrs);
collector.run();
IfSnmpCollector snmpc = collector.getSnmpCollector();
if (snmpc == null) {
log().debug("SNMP Collector from DB primary SNMP interface is null");
} else {
gotSnmpCollection = true;
collectorMap.put(ifaddrString, collector);
if (log().isDebugEnabled()) {
log().debug("SNMP data collected from DB primary SNMP interface " + ifaddrString);
}
if (!snmpc.hasIfTable()) {
log().debug("SNMP Collector has no IfTable");
}
if (!snmpc.hasIpAddrTable() || snmpc.getIfIndex(snmpc.getCollectorTargetAddress()) == -1) {
log().debug("SNMP Collector has no IpAddrTable. Assume its a lame SNMP host.");
}
}
return gotSnmpCollection;
}
private InetAddress updatePrimarySnmpInterface(Connection dbc, DbNodeEntry dbNodeEntry, Map<String, IfCollector> collectorMap, InetAddress oldPriIf) throws SQLException {
/*
* Now that all interfaces have been added to the
* database we can update the 'primarySnmpInterface'
* field of the ipInterface table. Necessary because
* the IP address must already be in the database
* to evaluate against a filter rule.
*
* First create a list of eligible loopback interfaces
* and a list of all eligible interfaces. Test in the
* following order:
*
* 1) strict = true (interface must be part of a Collectd
* package) and loopback.
*
* 2) strict = true and all eligible interfaces.
* strict = false and loopback.
*
* 4) strict = false and all eligible interfaces.
*/
boolean strict = true;
CollectdConfigFactory.getInstance().rebuildPackageIpListMap();
IfSnmpCollector snmpc = findSnmpCollector(collectorMap);
List<InetAddress> snmpLBAddresses = buildLBSnmpAddressList(collectorMap, snmpc);
List<InetAddress> snmpAddresses = buildSnmpAddressList(collectorMap, snmpc);
// first set the value of issnmpprimary for secondaries
Iterator<InetAddress> iter = snmpAddresses.iterator();
while(iter.hasNext()) {
InetAddress addr = iter.next();
final String addrString = str(addr);
if (CollectdConfigFactory.getInstance().isServiceCollectionEnabled(addrString, "SNMP")) {
final DBUtils d = new DBUtils(RescanProcessor.class);
try {
PreparedStatement stmt = dbc.prepareStatement("UPDATE ipInterface SET isSnmpPrimary='S' WHERE nodeId=? AND ipAddr=? AND isManaged!='D'");
d.watch(stmt);
stmt.setInt(1, dbNodeEntry.getNodeId());
stmt.setString(2, addrString);
stmt.executeUpdate();
log().debug("updatePrimarySnmpInterface: updated " + addrString + " to secondary.");
} finally {
d.cleanUp();
}
}
}
InetAddress newSnmpPrimaryIf = CapsdConfigFactory.getInstance().determinePrimarySnmpInterface(snmpLBAddresses, strict);
String psiType = ConfigFileConstants.getFileName(ConfigFileConstants.COLLECTD_CONFIG_FILE_NAME) + " loopback addresses";
if (newSnmpPrimaryIf == null) {
newSnmpPrimaryIf = CapsdConfigFactory.getInstance().determinePrimarySnmpInterface(snmpAddresses, strict);
psiType = ConfigFileConstants.getFileName(ConfigFileConstants.COLLECTD_CONFIG_FILE_NAME) + " addresses";
}
strict = false;
if (newSnmpPrimaryIf == null) {
newSnmpPrimaryIf = CapsdConfigFactory.getInstance().determinePrimarySnmpInterface(snmpLBAddresses, strict);
psiType = "DB loopback addresses";
}
if (newSnmpPrimaryIf == null) {
newSnmpPrimaryIf = CapsdConfigFactory.getInstance().determinePrimarySnmpInterface(snmpAddresses, strict);
psiType = "DB addresses";
}
if (newSnmpPrimaryIf == null) {
newSnmpPrimaryIf = snmpc.getCollectorTargetAddress();
psiType = "SNMP collector target address";
}
if (newSnmpPrimaryIf != null) {
if (log().isDebugEnabled()) {
log().debug("updatePrimarySnmpInterface: primary SNMP interface is: " + newSnmpPrimaryIf + ", selected from " + psiType);
}
SuspectEventProcessor.setPrimarySnmpInterface(dbc, dbNodeEntry, newSnmpPrimaryIf, oldPriIf);
} else {
log().debug("SuspectEventProcessor: Unable to determine a primary SNMP interface");
}
/*
* Now that we've identified the new primary SNMP
* interface we can determine if it is necessary to
* generate certain SNMP data collection related
* events
*/
generateSnmpDataCollectionEvents(dbNodeEntry, oldPriIf, newSnmpPrimaryIf);
return newSnmpPrimaryIf;
}
/**
* @param collectorMap
* @return
*/
private static IfSnmpCollector findSnmpCollector(Map<String, IfCollector> collectorMap) {
for (Iterator<IfCollector> iter = collectorMap.values().iterator(); iter.hasNext();) {
IfCollector collector = iter.next();
if (collector.hasSnmpCollection()) {
return collector.getSnmpCollector();
}
}
return null;
}
private DbIpInterfaceEntry[] getInterfaces(DbNodeEntry dbNodeEntry) {
/*
* If this is a forced rescan then retrieve all the interfaces
* associated with this node and perform collections against them.
* Otherwise, this is a regularly scheduled rescan, only the
* node's managed interfaces are to be retrieved and collected.
*/
DbIpInterfaceEntry[] dbInterfaces = null;
/*
* Retrieve list of interfaces associated with this nodeID
* from the database
*/
if (log().isDebugEnabled()) {
log().debug("retrieving managed interfaces for node: " + getNodeId());
}
try {
dbInterfaces = (m_forceRescan ? dbNodeEntry.getInterfaces() : dbNodeEntry.getManagedInterfaces());
} catch (NullPointerException npE) {
log().error("RescanProcessor: Null pointer when retrieving "+(m_forceRescan ? "" : "managed")+" interfaces for node " + getNodeId(), npE);
log().error("Rescan failed for node w/ nodeid " + getNodeId());
} catch (SQLException sqlE) {
log().error("RescanProcessor: unable to load interface info for nodeId " + getNodeId() + " from the database.", sqlE);
log().error("Rescan failed for node w/ nodeid " + getNodeId());
}
return dbInterfaces;
}
private DbNodeEntry getNode() {
DbNodeEntry dbNodeEntry = null;
/*
* Get DbNodeEntry object which represents this node and
* load it from the database
*/
try {
dbNodeEntry = DbNodeEntry.get(getNodeId());
} catch (SQLException e) {
log().error("RescanProcessor: unable to load node info for nodeId "
+ getNodeId() + " from the database.", e);
log().error("Rescan failed for node w/ nodeid "
+ getNodeId());
}
return dbNodeEntry;
}
/**
* Determines if any SNMP data collection related events need to be
* generated based upon the results of the current rescan. If necessary will
* generate one of the following events: 'reinitializePrimarySnmpInterface'
* 'primarySnmpInterfaceChanged'
*
* @param nodeEntry
* DbNodeEntry object of the node being rescanned.
* @param oldPriIf
* Previous primary SNMP interface (from the DB).
* @param primarySnmpIf
* Primary SNMP interface as determined by the current rescan.
*/
private void generateSnmpDataCollectionEvents(DbNodeEntry nodeEntry, InetAddress oldPriIf, InetAddress primarySnmpIf) {
/*
* NOTE: If SNMP service was not previously supported on this node
* then oldPriIf will be null. If this is the case
* then no need to generate primarySnmpInterfaceChanged event,
* the nodeGainedService event generated due to the addition of
* SNMP is sufficient.
*/
boolean reInit = true;
if (oldPriIf == null && primarySnmpIf != null) {
reInit = false;
log().debug("generateSnmpDataCollectionEvents: Either SNMP support was recently enabled on this node, or node doesn't support ipAddrTable MIB.");
m_eventList.add(createPrimarySnmpInterfaceChangedEvent(nodeEntry.getNodeId(), primarySnmpIf, null));
} else {
/*
* A PrimarySnmpInterfaceChanged event is generated if the scan
* found a different primary SNMP interface than what is stored
* in the database.
*/
if (primarySnmpIf != null && !oldPriIf.equals(primarySnmpIf)) {
if (log().isDebugEnabled()) {
log().debug("generateSnmpDataCollectionEvents: primary SNMP interface has changed. Was: " + str(oldPriIf) + " Is: " + str(primarySnmpIf));
}
m_eventList.add(createPrimarySnmpInterfaceChangedEvent(nodeEntry.getNodeId(), primarySnmpIf, oldPriIf));
reInit = false;
}
}
/*
* An interface map is built by the SNMP poller when the primary
* SNMP interface is initialized by the service monitor. This map
* is used to associate each interface on the node with its
* ifIndex and ifLabel for purposes of performing data collection
* and storage. If an ifIndex has changed for one or more
* interfaces or if a new interface was added to the node then
* the primary SNMP interface must be reinitialized so that this
* interface map can be rebuilt with the new information.
*/
if (reInit && (m_ifIndexOnNodeChangedFlag || m_snmpIfTableChangedFlag)) {
if (log().isDebugEnabled()) {
log().debug("generateSnmpDataCollectionEvents: Generating reinitializeSnmpInterface event for interface " + str(primarySnmpIf));
}
m_eventList.add(createReinitializePrimarySnmpInterfaceEvent(nodeEntry.getNodeId(), primarySnmpIf));
}
}
private static EventBuilder eventBuilder(String uei) {
return new EventBuilder(uei, "OpenNMS.Capsd").setHost(Capsd.getLocalHostAddress());
}
private static EventBuilder nodeEventBuilder(String uei, long nodeId) {
return eventBuilder(uei).setNodeid(nodeId);
}
private static EventBuilder interfaceEventBuilder(String uei, long nodeId, String ipAddr) {
return eventBuilder(uei).setNodeid(nodeId).setInterface(addr(ipAddr));
}
private static EventBuilder serviceEventBuilder(String uei, long nodeId, String ipAddr, String svc) {
return eventBuilder(uei).setNodeid(nodeId).setInterface(addr(ipAddr)).setService(svc);
}
/**
* This method is responsible for generating a nodeLabelChanged event and
* adding it to the event list.
*
* @param updatedEntry
* Updated node entry object
* @param originalEntry
* Original node entry object
*/
private static Event createNodeLabelChangedEvent(DbNodeEntry updatedEntry, DbNodeEntry originalEntry) {
if (log().isDebugEnabled()) {
log().debug("createNodeLabelChangedEvent: nodeId: " + updatedEntry.getNodeId() + " oldLabel: '" + originalEntry.getLabel() + "' oldSource: '" + originalEntry.getLabelSource() + "' newLabel: '" + updatedEntry.getLabel() + "' newLabelSource: '" + updatedEntry.getLabelSource() + "'");
}
EventBuilder bldr = nodeEventBuilder(EventConstants.NODE_LABEL_CHANGED_EVENT_UEI, updatedEntry.getNodeId());
if (originalEntry.getLabel() != null) {
bldr.addParam(EventConstants.PARM_OLD_NODE_LABEL, originalEntry.getLabel());
bldr.addParam(EventConstants.PARM_OLD_NODE_LABEL_SOURCE, originalEntry.getLabelSource());
}
if (updatedEntry.getLabel() != null) {
bldr.addParam(EventConstants.PARM_NEW_NODE_LABEL, updatedEntry.getLabel());
bldr.addParam(EventConstants.PARM_NEW_NODE_LABEL_SOURCE, updatedEntry.getLabelSource());
}
if (log().isDebugEnabled()) {
log().debug("createNodeLabelChangedEvent: successfully created nodeLabelChanged event for nodeid: " + updatedEntry.getNodeId());
}
// Add event to the list of events to be sent out.
return bldr.getEvent();
}
/**
* This method is responsible for generating a nodeInfoChanged event and
* adding it to the event list.
*
* @param updatedEntry
* Updated node entry object
* @param originalEntry
* Original node entry object
*/
private static Event createNodeInfoChangedEvent(DbNodeEntry updatedEntry, DbNodeEntry originalEntry) {
if (log().isDebugEnabled()) {
log().debug("createNodeInfoChangedEvent: nodeId: " + updatedEntry.getNodeId());
}
EventBuilder bldr = nodeEventBuilder(EventConstants.NODE_INFO_CHANGED_EVENT_UEI, updatedEntry.getNodeId());
// SysOID
if (updatedEntry.getSystemOID() != null) {
bldr.addParam(EventConstants.PARM_NODE_SYSOID, updatedEntry.getSystemOID());
}
// SysName
if (updatedEntry.getSystemName() != null) {
bldr.addParam(EventConstants.PARM_NODE_SYSNAME, updatedEntry.getSystemName());
}
// SysDescription
if (updatedEntry.getSystemDescription() != null) {
bldr.addParam(EventConstants.PARM_NODE_SYSDESCRIPTION, updatedEntry.getSystemDescription());
}
// SysLocation
if (updatedEntry.getSystemLocation() != null) {
bldr.addParam(EventConstants.PARM_NODE_SYSLOCATION, updatedEntry.getSystemLocation());
}
// SysContact
if (updatedEntry.getSystemContact() != null) {
bldr.addParam(EventConstants.PARM_NODE_SYSCONTACT, updatedEntry.getSystemContact());
}
// NetBIOS name
if (updatedEntry.getNetBIOSName() != null) {
bldr.addParam(EventConstants.PARM_NODE_NETBIOS_NAME, updatedEntry.getNetBIOSName());
}
// Domain name
if (updatedEntry.getDomainName() != null) {
bldr.addParam(EventConstants.PARM_NODE_DOMAIN_NAME, updatedEntry.getDomainName());
}
// Operating System
if (updatedEntry.getOS() != null) {
bldr.addParam(EventConstants.PARM_NODE_OPERATING_SYSTEM, updatedEntry.getOS());
}
if (log().isDebugEnabled()) {
log().debug("createNodeInfoChangedEvent: successfully created nodeInfoChanged event for nodeid: " + updatedEntry.getNodeId());
}
// Add event to the list of events to be sent out.
return bldr.getEvent();
}
/**
* This method is responsible for generating a primarySnmpInterfaceChanged
* event and adding it to the event list.
*
* @param nodeId
* Nodeid of node being rescanned.
* @param newPrimaryIf
* new primary SNMP interface address
* @param oldPrimaryIf
* old primary SNMP interface address
* @return
*/
private static Event createPrimarySnmpInterfaceChangedEvent(final int nodeId, final InetAddress newPrimaryIf, final InetAddress oldPrimaryIf) {
String oldPrimaryAddr = null;
if (oldPrimaryIf != null) {
oldPrimaryAddr = str(oldPrimaryIf);
}
String newPrimaryAddr = null;
if (newPrimaryIf != null) {
newPrimaryAddr = str(newPrimaryIf);
}
if (log().isDebugEnabled()) {
log().debug("createPrimarySnmpInterfaceChangedEvent: nodeId: " + nodeId + "oldPrimarySnmpIf: '" + oldPrimaryAddr + "' newPrimarySnmpIf: '" + newPrimaryAddr + "'");
}
final EventBuilder bldr = serviceEventBuilder(EventConstants.PRIMARY_SNMP_INTERFACE_CHANGED_EVENT_UEI, nodeId, newPrimaryAddr, "SNMP");
if (oldPrimaryAddr != null) {
bldr.addParam(EventConstants.PARM_OLD_PRIMARY_SNMP_ADDRESS, oldPrimaryAddr);
}
if (newPrimaryAddr != null) {
bldr.addParam(EventConstants.PARM_NEW_PRIMARY_SNMP_ADDRESS, newPrimaryAddr);
}
if (log().isDebugEnabled()) {
log().debug("createPrimarySnmpInterfaceChangedEvent: successfully created primarySnmpInterfaceChanged event for nodeid: " + nodeId);
}
// Add event to the list of events to be sent out.
return bldr.getEvent();
}
/**
* This method is responsible for generating a interfaceIndexChanged event
* and adding it to the event list.
*
* @param updatedEntry
* updated IP interface database entry
* @param originalEntry
* original IP interface database entry
* @return
*/
private static Event createInterfaceIndexChangedEvent(final DbIpInterfaceEntry updatedEntry, final DbIpInterfaceEntry originalEntry) {
if (log().isDebugEnabled()) {
log().debug("createInterfaceIndexChangedEvent: nodeId: " + updatedEntry.getNodeId() + " oldIfIndex: " + originalEntry.getIfIndex() + " newIfIndex: " + updatedEntry.getIfIndex());
}
EventBuilder bldr = interfaceEventBuilder(EventConstants.INTERFACE_INDEX_CHANGED_EVENT_UEI, updatedEntry.getNodeId(), str(updatedEntry.getIfAddress()));
bldr.addParam(EventConstants.PARM_OLD_IFINDEX, originalEntry.getIfIndex());
bldr.addParam(EventConstants.PARM_NEW_IFINDEX, updatedEntry.getIfIndex());
if (log().isDebugEnabled()) {
log().debug("createInterfaceIndexChangedEvent: successfully created interfaceIndexChanged event for nodeid: " + updatedEntry.getNodeId());
}
// Add event to the list of events to be sent out.
return bldr.getEvent();
}
/**
* This method is responsible for generating an ipHostNameChanged event and
* adding it to the event list.
*
* @param updatedEntry
* updated IP interface database entry
* @param originalEntry
* original IP interface database entry
* @return
*/
private static Event createIpHostNameChangedEvent(final DbIpInterfaceEntry updatedEntry, final DbIpInterfaceEntry originalEntry) {
if (log().isDebugEnabled()) {
log().debug("createIpHostNameChangedEvent: nodeId: " + updatedEntry.getNodeId() + " oldHostName: " + originalEntry.getHostname() + " newHostName: " + updatedEntry.getHostname());
}
EventBuilder bldr = interfaceEventBuilder(EventConstants.INTERFACE_IP_HOSTNAME_CHANGED_EVENT_UEI, updatedEntry.getNodeId(), str(updatedEntry.getIfAddress()));
// Add old IP Hostname
if (originalEntry.getHostname() != null) {
bldr.addParam(EventConstants.PARM_OLD_IP_HOSTNAME, originalEntry.getHostname());
}
// Add new IP Hostname
if (updatedEntry.getHostname() != null) {
bldr.addParam(EventConstants.PARM_IP_HOSTNAME, updatedEntry.getHostname());
}
if (log().isDebugEnabled()) {
log().debug("createIpHostNameChangedEvent: successfully created ipHostNameChanged event for nodeid: " + updatedEntry.getNodeId());
}
// Add event to the list of events to be sent out.
return bldr.getEvent();
}
/**
* This method is responsible for generating a interfaceReparented event and
* adding it to the event list.
*
* @param newNode
* Entry of node under which the interface was added.
* @param oldNodeId
* Node identifier of node from which the interface was removed.
* @param reparentedIf
* Reparented interface
* @return
*/
private static Event createInterfaceReparentedEvent(final DbNodeEntry newNode, final int oldNodeId, final InetAddress reparentedIf) {
final String reparentedAddress = str(reparentedIf);
if (log().isDebugEnabled()) {
log().debug("createInterfaceReparentedEvent: ifAddr: " + reparentedAddress + " oldNodeId: " + oldNodeId + " newNodeId: " + newNode.getNodeId());
}
EventBuilder bldr = interfaceEventBuilder(EventConstants.INTERFACE_REPARENTED_EVENT_UEI, newNode.getNodeId(), reparentedAddress);
// Add old node id
bldr.addParam(EventConstants.PARM_OLD_NODEID, oldNodeId);
// Add new node id
bldr.addParam(EventConstants.PARM_NEW_NODEID, newNode.getNodeId());
// Add ip host name
bldr.addParam(EventConstants.PARM_IP_HOSTNAME, reparentedIf.getHostName());
// Add node label and node label source
if (newNode.getLabel() != null) {
bldr.addParam(EventConstants.PARM_NODE_LABEL, newNode.getLabel());
bldr.addParam(EventConstants.PARM_NODE_LABEL_SOURCE, newNode.getLabelSource());
}
// Add nodeSysName
if (newNode.getSystemName() != null) {
bldr.addParam(EventConstants.PARM_NODE_SYSNAME, newNode.getSystemName());
}
// Add nodeSysDescription
if (newNode.getSystemDescription() != null) {
bldr.addParam(EventConstants.PARM_NODE_SYSDESCRIPTION, newNode.getSystemDescription());
}
if (log().isDebugEnabled()) {
log().debug("createInterfaceReparentedEvent: successfully created interfaceReparented event for nodeid/interface: " + newNode.getNodeId() + "/" + reparentedAddress);
}
// Add event to the list of events to be sent out.
return bldr.getEvent();
}
/**
* This method is responsible for generating a duplicateNodeDeleted event
* and adding it to the event list.
*
* @param deletedNode
* Entry of duplciate node which was deleted.
* @return
*/
private static Event createDuplicateNodeDeletedEvent(DbNodeEntry deletedNode) {
if (log().isDebugEnabled()) {
log().debug("createDuplicateNodeDeletedEvent: delete nodeid: " + deletedNode.getNodeId());
}
EventBuilder bldr = nodeEventBuilder(EventConstants.DUP_NODE_DELETED_EVENT_UEI, deletedNode.getNodeId());
if (log().isDebugEnabled()) {
log().debug("createDuplicateNodeDeletedEvent: successfully created duplicateNodeDeleted event for nodeid: " + deletedNode.getNodeId());
}
// Add event to the list of events to be sent out.
return bldr.getEvent();
}
/**
* This method is responsible for generating a nodeGainedInterface event and
* adding it to the event list.
*
* @param ifEntry
* Entry of new interface.
* @return
*/
private static Event createNodeGainedInterfaceEvent(DbIpInterfaceEntry ifEntry) {
final String ifAddress = str(ifEntry.getIfAddress());
if (log().isDebugEnabled()) {
log().debug("createNodeGainedInterfaceEvent: nodeId: " + ifEntry.getNodeId() + " interface: " + ifAddress);
}
EventBuilder bldr = interfaceEventBuilder(EventConstants.NODE_GAINED_INTERFACE_EVENT_UEI, ifEntry.getNodeId(), ifAddress);
// Add ip host name
bldr.addParam(EventConstants.PARM_IP_HOSTNAME, ifEntry.getHostname() == null ? "" : ifEntry.getHostname());
// Add discovery method
bldr.addParam(EventConstants.PARM_METHOD, "icmp");
if (log().isDebugEnabled()) {
log().debug("createNodeGainedInterfaceEvent: successfully created nodeGainedInterface event for nodeid: " + ifEntry.getNodeId());
}
// Add event to the list of events to be sent out.
return bldr.getEvent();
}
/**
* This method is responsible for generating a duplicateIpAddress event and
* adding it to the event list.
*
* @param ifEntry
* Entry of new interface.
* @return
*/
private static Event createDuplicateIpAddressEvent(final DbIpInterfaceEntry ifEntry) {
final String ifAddress = str(ifEntry.getIfAddress());
if (log().isDebugEnabled()) {
log().debug("createDuplicateIpAddressEvent: nodeId: " + ifEntry.getNodeId() + " interface: " + ifAddress);
}
EventBuilder bldr = interfaceEventBuilder(EventConstants.DUPLICATE_IPINTERFACE_EVENT_UEI, ifEntry.getNodeId(), ifAddress);
bldr.addParam(EventConstants.PARM_IP_HOSTNAME, ifEntry.getHostname() == null ? "" : ifEntry.getHostname());
// Add discovery method
bldr.addParam(EventConstants.PARM_METHOD, "icmp");
if (log().isDebugEnabled()) {
log().debug("createDuplicateIpAddressEvent: successfully created duplicateIpAddress event for nodeid: " + ifEntry.getNodeId());
}
// Add event to the list of events to be sent out.
return bldr.getEvent();
}
/**
* This method is responsible for generating a nodeGainedService event and
* adding it to the event list.
*
* @param nodeEntry
* Entry of node which has gained a service
* @param ifEntry
* Entry of interface which has gained a service
* @param svcName
* Service name
* @return
*/
private static Event createNodeGainedServiceEvent(final DbNodeEntry nodeEntry, final DbIpInterfaceEntry ifEntry, final String svcName) {
final String ifAddress = str(ifEntry.getIfAddress());
if (log().isDebugEnabled()) {
log().debug("createNodeGainedServiceEvent: nodeId: " + ifEntry.getNodeId() + " interface: " + ifAddress + " service: " + svcName);
}
EventBuilder bldr = serviceEventBuilder(EventConstants.NODE_GAINED_SERVICE_EVENT_UEI, ifEntry.getNodeId(), ifAddress, svcName);
// Add ip host name
bldr.addParam(EventConstants.PARM_IP_HOSTNAME, ifEntry.getHostname() == null ? "" : ifEntry.getHostname());
// Add nodeSysName
if (nodeEntry.getSystemName() != null) {
bldr.addParam(EventConstants.PARM_NODE_SYSNAME, nodeEntry.getSystemName());
}
// Add nodeSysDescription
if (nodeEntry.getSystemDescription() != null) {
bldr.addParam(EventConstants.PARM_NODE_SYSDESCRIPTION, nodeEntry.getSystemDescription());
}
if (log().isDebugEnabled()) {
log().debug("createNodeGainedServiceEvent: successfully created nodeGainedService event for nodeid: " + ifEntry.getNodeId());
}
// Add event to the list of events to be sent out.
return bldr.getEvent();
}
/**
* This method is responsible for generating a suspendPollingService event
* and adding it to the event list.
*
* @param nodeEntry
* Entry of node for which a service is to be polled
* @param ifEntry
* Entry of interface which a service is to be polled
* @param svcName
* Service name
* @return
*/
private static Event createSuspendPollingServiceEvent(final DbNodeEntry nodeEntry, final DbIpInterfaceEntry ifEntry, final String svcName) {
final String ifAddress = str(ifEntry.getIfAddress());
final EventBuilder bldr = serviceEventBuilder(EventConstants.SUSPEND_POLLING_SERVICE_EVENT_UEI, ifEntry.getNodeId(), ifAddress, svcName);
// Add ip host name
bldr.addParam(EventConstants.PARM_IP_HOSTNAME, ifEntry.getHostname() == null ? "" : ifEntry.getHostname());
// Add nodeSysName
if (nodeEntry.getSystemName() != null) {
bldr.addParam(EventConstants.PARM_NODE_SYSNAME, nodeEntry.getSystemName());
}
// Add nodeSysDescription
if (nodeEntry.getSystemDescription() != null) {
bldr.addParam(EventConstants.PARM_NODE_SYSDESCRIPTION, nodeEntry.getSystemDescription());
}
if (log().isDebugEnabled()) {
log().debug("suspendPollingServiceEvent: Created suspendPollingService event for nodeid: " + ifEntry.getNodeId() + " interface: " + ifAddress + " service: " + svcName);
}
// Add event to the list of events to be sent out.
return bldr.getEvent();
}
/**
* This method is responsible for generating a resumePollingService event
* and adding it to the event list.
*
* @param nodeEntry
* Entry of node for which a service is to be polled
* @param ifEntry
* Entry of interface which a service is to be polled
* @param svcName
* Service name
* @return
*/
private static Event createResumePollingServiceEvent(final DbNodeEntry nodeEntry, final DbIpInterfaceEntry ifEntry, final String svcName) {
final String ifAddress = str(ifEntry.getIfAddress());
final EventBuilder bldr = serviceEventBuilder(EventConstants.RESUME_POLLING_SERVICE_EVENT_UEI, ifEntry.getNodeId(), ifAddress, svcName);
// Add ip host name
bldr.addParam(EventConstants.PARM_IP_HOSTNAME, ifEntry.getHostname() == null ? "" : ifEntry.getHostname());
// Add nodeSysName
if (nodeEntry.getSystemName() != null) {
bldr.addParam(EventConstants.PARM_NODE_SYSNAME, nodeEntry.getSystemName());
}
// Add nodeSysDescription
if (nodeEntry.getSystemDescription() != null) {
bldr.addParam(EventConstants.PARM_NODE_SYSDESCRIPTION, nodeEntry.getSystemDescription());
}
if (log().isDebugEnabled()) {
log().debug("resumePollingServiceEvent: Created resumePollingService event for nodeid: " + ifEntry.getNodeId() + " interface: " + ifAddress + " service: " + svcName);
}
// Add event to the list of events to be sent out.
return bldr.getEvent();
}
/**
* This method is responsible for generating a snmpConflictsWithDb event and
* adding it to the event list.
*
* @param nodeEntry Entry of node for which a conflict exits
* @return
*/
private static Event createSnmpConflictsWithDbEvent(DbNodeEntry nodeEntry) {
EventBuilder bldr = nodeEventBuilder(EventConstants.SNMP_CONFLICTS_WITH_DB_EVENT_UEI, nodeEntry.getNodeId());
// Add node label
bldr.addParam(EventConstants.PARM_NODE_LABEL, nodeEntry.getLabel() == null ? "" : nodeEntry.getLabel());
// Add nodeSysName
if (nodeEntry.getSystemName() != null) {
bldr.addParam(EventConstants.PARM_NODE_SYSNAME, nodeEntry.getSystemName());
}
// Add nodeSysDescription
if (nodeEntry.getSystemDescription() != null) {
bldr.addParam(EventConstants.PARM_NODE_SYSDESCRIPTION, nodeEntry.getSystemDescription());
}
if (log().isDebugEnabled()) {
log().debug("snmpConflictsWithDbEvent: Created snmpConflictsWithDbEvent for nodeid: " + nodeEntry.getNodeId());
}
// Add event to the list of events to be sent out.
return bldr.getEvent();
}
/**
* This method is responsible for generating a rescanCompleted event and
* adding it to the event list.
*
* @param nodeEntry Entry of node which was rescanned
* @return
*/
private static Event createRescanCompletedEvent(DbNodeEntry nodeEntry) {
EventBuilder bldr = nodeEventBuilder(EventConstants.RESCAN_COMPLETED_EVENT_UEI, nodeEntry.getNodeId());
// Add node label
bldr.addParam(EventConstants.PARM_NODE_LABEL, nodeEntry.getLabel() == null ? "" : nodeEntry.getLabel());
if (log().isDebugEnabled()) {
log().debug("rescanCompletedEvent: Created rescanCompletedEvent for nodeid: " + nodeEntry.getNodeId());
}
// Add event to the list of events to be sent out.
return bldr.getEvent();
}
/**
* This method is responsible for generating a interfaceSupportsSNMPEvent
* event and adding it to the event list.
*
* @param ifEntry
* Entry of interface which has gained a service
* @return
*/
private static Event createInterfaceSupportsSNMPEvent(final DbIpInterfaceEntry ifEntry) {
final String ifAddress = str(ifEntry.getIfAddress());
if (log().isDebugEnabled()) {
log().debug("createInterfaceSupportsSNMPEvent: nodeId: " + ifEntry.getNodeId() + " interface: " + ifAddress);
}
final EventBuilder bldr = interfaceEventBuilder(EventConstants.INTERFACE_SUPPORTS_SNMP_EVENT_UEI, ifEntry.getNodeId(), ifAddress);
if (log().isDebugEnabled()) {
log().debug("interfaceSupportsSNMPEvent: successfully created interfaceSupportsSNMPEvent event for nodeid: " + ifEntry.getNodeId());
}
// Add event to the list of events to be sent out.
return bldr.getEvent();
}
/**
* This method is responsible for generating a
* reinitializePrimarySnmpInterface event and adding it to the event list.
*
* @param nodeId
* Nodeid of node being rescanned.
* @param primarySnmpIf
* Primary SNMP interface address.
* @return
*/
private static Event createReinitializePrimarySnmpInterfaceEvent(final int nodeId, final InetAddress primarySnmpIf) {
final String primaryAddress = str(primarySnmpIf);
if (log().isDebugEnabled()) {
log().debug("reinitializePrimarySnmpInterface: nodeId: " + nodeId + " interface: " + primaryAddress);
}
EventBuilder bldr = interfaceEventBuilder(EventConstants.REINITIALIZE_PRIMARY_SNMP_INTERFACE_EVENT_UEI, nodeId, primaryAddress);
if (log().isDebugEnabled()) {
log().debug("createReinitializePrimarySnmpInterfaceEvent: successfully created reinitializePrimarySnmpInterface event for interface: " + primaryAddress);
}
// Add event to the list of events to be sent out.
return bldr.getEvent();
}
/**
* Responsible for setting the Set used to track rescans that
* are already enqueued for processing. Should be called once by Capsd
* at startup.
*
* @param queuedRescanTracker
* The synchronized Set to use
*/
public static synchronized void setQueuedRescansTracker(Set<Integer> queuedRescanTracker) {
m_queuedRescanTracker = Collections.synchronizedSet(queuedRescanTracker);
}
/**
* Is a rescan already enqueued for a given node ID?
*
* @param nodeId a {@link java.lang.Integer} object.
* @return a boolean.
*/
public static boolean isRescanQueuedForNode(Integer nodeId) {
synchronized(m_queuedRescanTracker) {
return (m_queuedRescanTracker.contains(nodeId));
}
}
} // end class