/*******************************************************************************
* 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.importer.operations;
import java.net.InetAddress;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.opennms.core.utils.InetAddressUtils;
import org.opennms.core.utils.LogUtils;
import org.opennms.core.utils.ThreadCategory;
import org.opennms.netmgt.capsd.IfSnmpCollector;
import org.opennms.netmgt.capsd.snmp.IfTableEntry;
import org.opennms.netmgt.importer.config.types.InterfaceSnmpPrimaryType;
import org.opennms.netmgt.dao.CategoryDao;
import org.opennms.netmgt.dao.DistPollerDao;
import org.opennms.netmgt.dao.NodeDao;
import org.opennms.netmgt.dao.ServiceTypeDao;
import org.opennms.netmgt.model.OnmsCategory;
import org.opennms.netmgt.model.OnmsIpInterface;
import org.opennms.netmgt.model.OnmsMonitoredService;
import org.opennms.netmgt.model.OnmsNode;
import org.opennms.netmgt.model.OnmsServiceType;
import org.opennms.netmgt.model.OnmsSnmpInterface;
import org.opennms.netmgt.model.PrimaryType;
import org.opennms.netmgt.xml.event.Event;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyAccessorFactory;
/**
* <p>Abstract AbstractSaveOrUpdateOperation class.</p>
*
* @author ranger
* @version $Id: $
*/
public abstract class AbstractSaveOrUpdateOperation extends AbstractImportOperation implements SaveOrUpdateOperation {
private final OnmsNode m_node;
private NodeDao m_nodeDao;
private DistPollerDao m_distPollerDao;
private OnmsIpInterface m_currentInterface;
private ServiceTypeDao m_svcTypeDao;
private CategoryDao m_categoryDao;
private ThreadLocal<HashMap<String, OnmsServiceType>> m_types;
private ThreadLocal<HashMap<String, OnmsCategory>> m_categories;
private IfSnmpCollector m_collector;
/**
* <p>Constructor for AbstractSaveOrUpdateOperation.</p>
*
* @param foreignSource a {@link java.lang.String} object.
* @param foreignId a {@link java.lang.String} object.
* @param nodeLabel a {@link java.lang.String} object.
* @param building a {@link java.lang.String} object.
* @param city a {@link java.lang.String} object.
*/
public AbstractSaveOrUpdateOperation(final String foreignSource, final String foreignId, final String nodeLabel, final String building, final String city) {
this(null, foreignSource, foreignId, nodeLabel, building, city);
}
/**
* <p>Constructor for AbstractSaveOrUpdateOperation.</p>
*
* @param nodeId a {@link java.lang.Integer} object.
* @param foreignSource a {@link java.lang.String} object.
* @param foreignId a {@link java.lang.String} object.
* @param nodeLabel a {@link java.lang.String} object.
* @param building a {@link java.lang.String} object.
* @param city a {@link java.lang.String} object.
*/
public AbstractSaveOrUpdateOperation(final Integer nodeId, final String foreignSource, final String foreignId, final String nodeLabel, final String building, final String city) {
m_node = new OnmsNode();
m_node.setId(nodeId);
m_node.setLabel(nodeLabel);
m_node.setLabelSource("U");
m_node.setType("A");
m_node.setForeignSource(foreignSource);
m_node.setForeignId(foreignId);
m_node.getAssetRecord().setBuilding(building);
m_node.getAssetRecord().setCity(city);
}
/** {@inheritDoc} */
public void foundInterface(final String ipAddr, final Object descr, final InterfaceSnmpPrimaryType snmpPrimary, final boolean managed, final int status) {
if ("".equals(ipAddr)) {
log().error("Found interface on node "+m_node.getLabel()+" with an empty ipaddr! Ignoring!");
// create a bogus OnmsIpInterface and set it to current to services we run across get ignored as well
m_currentInterface = new OnmsIpInterface();
return;
}
m_currentInterface = new OnmsIpInterface(ipAddr, m_node);
m_currentInterface.setIsManaged(status == 3 ? "U" : "M");
m_currentInterface.setIsSnmpPrimary(PrimaryType.get(snmpPrimary.toString()));
//m_currentInterface.setIpStatus(status == 3 ? new Integer(3) : new Integer(1));
if (InterfaceSnmpPrimaryType.P.equals(snmpPrimary)) {
final InetAddress addr = InetAddressUtils.addr(ipAddr);
if (addr == null) {
LogUtils.errorf(this, "Unable to resolve address of snmpPrimary interface for node %s", m_node.getLabel());
}
m_collector = new IfSnmpCollector(addr);
}
//FIXME: verify this doesn't conflict with constructor. The constructor already adds this
//interface to the node.
m_node.addIpInterface(m_currentInterface);
}
/**
* <p>gatherAdditionalData</p>
*/
public void gatherAdditionalData() {
updateSnmpData();
}
/**
* <p>persist</p>
*
* @return a {@link java.util.List} object.
*/
public List<Event> persist() {
return doPersist();
}
/**
* <p>doPersist</p>
*
* @return a {@link java.util.List} object.
*/
protected abstract List<Event> doPersist();
/**
* <p>updateSnmpData</p>
*/
protected void updateSnmpData() {
if (m_collector != null) {
m_collector.run();
}
updateSnmpDataForNode();
updateSnmpDataForSnmpInterfaces();
for (OnmsIpInterface ipIf : m_node.getIpInterfaces()) {
resolveIpHostname(ipIf);
updateSnmpDataForInterface(ipIf);
}
}
private void updateSnmpDataForSnmpInterfaces() {
if (m_collector != null && m_collector.hasIfTable()) {
for(IfTableEntry entry : m_collector.getIfTable()) {
Integer ifIndex = entry.getIfIndex();
if (ifIndex == null) continue;
log().debug("Updating SNMP Interface with ifIndex "+ifIndex);
// first look to see if an snmpIf was created already
OnmsSnmpInterface snmpIf = m_node.getSnmpInterfaceWithIfIndex(ifIndex);
if (snmpIf == null) {
// if not then create one
snmpIf = new OnmsSnmpInterface(m_node, ifIndex);
}
snmpIf.setIfAlias(m_collector.getIfAlias(ifIndex));
snmpIf.setIfName(m_collector.getIfName(ifIndex));
snmpIf.setIfType(getIfType(ifIndex));
snmpIf.setNetMask(getNetMask(ifIndex));
snmpIf.setIfAdminStatus(getAdminStatus(ifIndex));
snmpIf.setIfDescr(m_collector.getIfDescr(ifIndex));
snmpIf.setIfSpeed(m_collector.getInterfaceSpeed(ifIndex));
snmpIf.setPhysAddr(m_collector.getPhysAddr(ifIndex));
}
}
}
private void updateSnmpDataForNode() {
if (m_collector != null && m_collector.hasSystemGroup()) {
m_node.setSysContact(m_collector.getSystemGroup().getSysContact());
m_node.setSysDescription(m_collector.getSystemGroup().getSysDescr());
m_node.setSysLocation(m_collector.getSystemGroup().getSysLocation());
m_node.setSysObjectId(m_collector.getSystemGroup().getSysObjectID());
}
}
/**
* <p>isSnmpDataForNodeUpToDate</p>
*
* @return a boolean.
*/
protected boolean isSnmpDataForNodeUpToDate() {
return m_collector != null && m_collector.hasSystemGroup();
}
/**
* <p>isSnmpDataForInterfacesUpToDate</p>
*
* @return a boolean.
*/
protected boolean isSnmpDataForInterfacesUpToDate() {
return m_collector != null && m_collector.hasIfTable() && m_collector.hasIpAddrTable();
}
private void updateSnmpDataForInterface(OnmsIpInterface ipIf) {
if (m_collector == null || !m_collector.hasIpAddrTable() || !m_collector.hasIfTable()) {
return;
}
final InetAddress inetAddr = ipIf.getIpAddress();
final String ipAddr = InetAddressUtils.str(inetAddr);
log().debug("Creating SNMP info for interface "+ipAddr);
int ifIndex = m_collector.getIfIndex(inetAddr);
if (ifIndex == -1) {
return;
}
// first look to see if an snmpIf was created already
OnmsSnmpInterface snmpIf = m_node.getSnmpInterfaceWithIfIndex(ifIndex);
if (snmpIf == null) {
// if not then create one
snmpIf = new OnmsSnmpInterface(m_node, new Integer(ifIndex));
snmpIf.setIfAlias(m_collector.getIfAlias(ifIndex));
snmpIf.setIfName(m_collector.getIfName(ifIndex));
snmpIf.setIfType(getIfType(ifIndex));
snmpIf.setNetMask(getNetMask(ifIndex));
snmpIf.setIfAdminStatus(getAdminStatus(ifIndex));
snmpIf.setIfDescr(m_collector.getIfDescr(ifIndex));
snmpIf.setIfSpeed(m_collector.getInterfaceSpeed(ifIndex));
snmpIf.setPhysAddr(m_collector.getPhysAddr(ifIndex));
}
snmpIf.setCollectionEnabled(true);
ipIf.setSnmpInterface(snmpIf);
//FIXME: Improve OpenNMS to provide these values
// ifOperStatus
}
private Integer getAdminStatus(int ifIndex) {
int adminStatus = m_collector.getAdminStatus(ifIndex);
return (adminStatus == -1 ? null : new Integer(adminStatus));
}
private Integer getIfType(int ifIndex) {
int ifType = m_collector.getIfType(ifIndex);
return (ifType == -1 ? null : new Integer(ifType));
}
private InetAddress getNetMask(int ifIndex) {
InetAddress[] ifAddressAndMask = m_collector.getIfAddressAndMask(ifIndex);
if (ifAddressAndMask != null && ifAddressAndMask.length > 1 && ifAddressAndMask[1] != null) {
return ifAddressAndMask[1];
}
return null;
}
private void resolveIpHostname(final OnmsIpInterface ipIf) {
final String ipAddress = InetAddressUtils.str(ipIf.getIpAddress());
ipIf.setIpHostName(ipAddress);
//
// DON'T DO THIS SINCE DNS DOESN'T RELIABLY AVOID HANGING
//
// log().info("Resolving Hostname for "+ipIf.getIpAddress());
// try {
// InetAddress addr = InetAddressUtils.addr(ipIf.getIpAddress());
// ipIf.setIpHostName(addr.getHostName());
// } catch (Throwable e) {
// if (ipIf.getIpHostName() == null)
// ipIf.setIpHostName(ipIf.getIpAddress());
// }
}
/** {@inheritDoc} */
public void foundMonitoredService(String serviceName) {
OnmsServiceType svcType = getServiceType(serviceName);
OnmsMonitoredService service = new OnmsMonitoredService(m_currentInterface, svcType);
service.setStatus("A");
m_currentInterface.getMonitoredServices().add(service);
}
/** {@inheritDoc} */
public void foundCategory(String name) {
OnmsCategory category = getCategory(name);
m_node.getCategories().add(category);
}
/** {@inheritDoc} */
public void foundAsset(String name, String value) {
BeanWrapper w = PropertyAccessorFactory.forBeanPropertyAccess(m_node.getAssetRecord());
try {
w.setPropertyValue(name, value);
} catch (BeansException e) {
ThreadCategory.getInstance(this.getClass()).warn("Could not set property on asset: " + name, e);
}
}
private OnmsServiceType getServiceType(String serviceName) {
preloadExistingTypes();
OnmsServiceType type = getTypes().get(serviceName);
if (type == null) {
type = m_svcTypeDao.findByName(serviceName);
if (type == null) {
type = new OnmsServiceType(serviceName);
m_svcTypeDao.save(type);
}
getTypes().put(serviceName, type);
}
return type;
}
private void preloadExistingTypes() {
if (getTypes() == null) {
setTypes(new HashMap<String, OnmsServiceType>());
for (OnmsServiceType svcType : m_svcTypeDao.findAll()) {
getTypes().put(svcType.getName(), svcType);
}
}
}
private void preloadExistingCategories() {
if (getCategories() == null) {
setCategories(new HashMap<String, OnmsCategory>());
for (OnmsCategory category : m_categoryDao.findAll()) {
getCategories().put(category.getName(), category);
}
}
}
/**
* <p>getNode</p>
*
* @return a {@link org.opennms.netmgt.model.OnmsNode} object.
*/
protected OnmsNode getNode() {
return m_node;
}
/**
* <p>getNodeDao</p>
*
* @return a {@link org.opennms.netmgt.dao.NodeDao} object.
*/
protected NodeDao getNodeDao() {
return m_nodeDao;
}
/**
* <p>getDistPollerDao</p>
*
* @return a {@link org.opennms.netmgt.dao.DistPollerDao} object.
*/
protected DistPollerDao getDistPollerDao() {
return m_distPollerDao;
}
private OnmsCategory getCategory(String name) {
preloadExistingCategories();
OnmsCategory category = getCategories().get(name);
if (category == null) {
category = m_categoryDao.findByName(name);
if (category == null) {
category = new OnmsCategory(name);
m_categoryDao.save(category);
}
getCategories().put(category.getName(), category);
}
return category;
}
/**
* <p>getIpAddrToInterfaceMap</p>
*
* @param imported a {@link org.opennms.netmgt.model.OnmsNode} object.
* @return a {@link java.util.Map} object.
*/
protected Map<String, OnmsIpInterface> getIpAddrToInterfaceMap(OnmsNode imported) {
Map<String, OnmsIpInterface> ipAddrToIface = new HashMap<String, OnmsIpInterface>();
for (final OnmsIpInterface iface : imported.getIpInterfaces()) {
final String ipAddress = InetAddressUtils.str(iface.getIpAddress());
ipAddrToIface.put(ipAddress, iface);
}
return ipAddrToIface;
}
private HashMap<String, OnmsServiceType> getTypes() {
return m_types.get();
}
private void setTypes(HashMap<String, OnmsServiceType> types) {
m_types.set(types);
}
private void setCategories(HashMap<String, OnmsCategory> categories) {
m_categories.set(categories);
}
private HashMap<String, OnmsCategory> getCategories() {
return m_categories.get();
}
/**
* <p>getCategoryDao</p>
*
* @return a {@link org.opennms.netmgt.dao.CategoryDao} object.
*/
public CategoryDao getCategoryDao() {
return m_categoryDao;
}
/**
* <p>setCategoryDao</p>
*
* @param categoryDao a {@link org.opennms.netmgt.dao.CategoryDao} object.
*/
public void setCategoryDao(CategoryDao categoryDao) {
m_categoryDao = categoryDao;
}
/**
* <p>setServiceTypeDao</p>
*
* @param svcTypeDao a {@link org.opennms.netmgt.dao.ServiceTypeDao} object.
*/
public void setServiceTypeDao(ServiceTypeDao svcTypeDao) {
m_svcTypeDao = svcTypeDao;
}
/**
* <p>setNodeDao</p>
*
* @param nodeDao a {@link org.opennms.netmgt.dao.NodeDao} object.
*/
public void setNodeDao(NodeDao nodeDao) {
m_nodeDao = nodeDao;
}
/**
* <p>setDistPollerDao</p>
*
* @param distPollerDao a {@link org.opennms.netmgt.dao.DistPollerDao} object.
*/
public void setDistPollerDao(DistPollerDao distPollerDao) {
m_distPollerDao = distPollerDao;
}
/**
* <p>setTypeCache</p>
*
* @param typeCache a {@link java.lang.ThreadLocal} object.
*/
public void setTypeCache(ThreadLocal<HashMap<String, OnmsServiceType>> typeCache) {
m_types = typeCache;
}
/**
* <p>setCategoryCache</p>
*
* @param categoryCache a {@link java.lang.ThreadLocal} object.
*/
public void setCategoryCache(ThreadLocal<HashMap<String, OnmsCategory>> categoryCache) {
m_categories = categoryCache;
}
/**
* <p>log</p>
*
* @return a {@link org.opennms.core.utils.ThreadCategory} object.
*/
protected ThreadCategory log() {
return ThreadCategory.getInstance(getClass());
}
/**
* <p>nullSafeEquals</p>
*
* @param o1 a {@link java.lang.Object} object.
* @param o2 a {@link java.lang.Object} object.
* @return a boolean.
*/
public boolean nullSafeEquals(Object o1, Object o2) {
return (o1 == null ? o2 == null : o1.equals(o2));
}
}