/*******************************************************************************
* This file is part of OpenNMS(R).
*
* Copyright (C) 2009-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.snmpinterfacepoller.pollable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.opennms.core.utils.ThreadCategory;
import org.opennms.netmgt.EventConstants;
import org.opennms.netmgt.model.OnmsSnmpInterface;
import org.opennms.netmgt.model.PollStatus;
import org.opennms.netmgt.scheduler.ReadyRunnable;
import org.opennms.netmgt.scheduler.Schedule;
import org.opennms.netmgt.snmp.SnmpAgentConfig;
import org.opennms.netmgt.snmpinterfacepoller.SnmpPollInterfaceMonitor;
/**
* Represents a PollableSnmpInterface
*
* @author <a href="mailto:antonio@opennms.it">Antonio Russo</a>
* @version $Id: $
*/
public class PollableSnmpInterface implements ReadyRunnable {
private volatile Schedule m_schedule;
private HashMap<Integer,OnmsSnmpInterface> m_snmpinterfaces;
private PollableSnmpInterfaceConfig m_snmppollableconfig;
private PollableInterface m_parent;
private String m_name;
private String m_criteria;
private SnmpAgentConfig m_agentConfig;
public class SnmpMinimalPollInterface {
final static int IF_UP=1;
final static int IF_DOWN=2;
final static int IF_UNKNOWN=0;
private final String[] s_statusNames = {"Unknown","InterfaceUp", "InterfaceDown"};
int ifindex;
int adminstatus;
int operstatus;
PollStatus m_status;
public SnmpMinimalPollInterface(int ifindex, int adminstatus,
int operstatus) {
this.ifindex = ifindex;
this.adminstatus = adminstatus;
this.operstatus = operstatus;
m_status = PollStatus.unknown();
}
public String decodeStatus(int status) {
if (status >= 0 && status <= 2) {
return s_statusNames[status];
}
return s_statusNames[0];
}
public int getIfindex() {
return ifindex;
}
public void setIfindex(int ifindex) {
this.ifindex = ifindex;
}
public int getAdminstatus() {
return adminstatus;
}
public void setAdminstatus(int adminstatus) {
if (adminstatus > 2 )
this.adminstatus = IF_UNKNOWN;
else this.adminstatus = adminstatus;
}
public int getOperstatus() {
return operstatus;
}
public void setOperstatus(int operstatus) {
if (operstatus > 2 )
this.operstatus = IF_UNKNOWN;
this.operstatus = operstatus;
}
public PollStatus getStatus() {
return m_status;
}
public void setStatus(PollStatus status) {
m_status = status;
}
}
/**
* <p>getSnmpinterfaces</p>
*
* @return a {@link java.util.Collection} object.
*/
public Collection<OnmsSnmpInterface> getSnmpinterfaces() {
return m_snmpinterfaces.values();
}
/**
* <p>setSnmpinterfaces</p>
*
* @param snmpinterfaces a {@link java.util.List} object.
*/
public void setSnmpinterfaces(List<OnmsSnmpInterface> snmpinterfaces) {
if (snmpinterfaces == null) {
log().debug("setting snmpinterfaces: got null, thread instantiated but at moment no interface found");
return;
}
// ifIndex -> operstatus
final Map<Integer, Integer> oldStatuses = new HashMap<Integer, Integer>();
for (final Integer ifIndex : m_snmpinterfaces.keySet()) {
final OnmsSnmpInterface iface = m_snmpinterfaces.get(ifIndex);
if (iface != null && iface.getIfOperStatus() != null) {
oldStatuses.put(ifIndex, iface.getIfOperStatus());
}
}
m_snmpinterfaces.clear();
for (OnmsSnmpInterface iface: snmpinterfaces) {
log().debug("setting snmpinterface:" + iface.toString());
if (iface != null && iface.getIfIndex() != null && iface.getIfIndex() > 0) {
final Integer oldStatus = oldStatuses.get(iface.getIfIndex());
m_snmpinterfaces.put(iface.getIfIndex(), iface);
if (iface.getIfAdminStatus() != null &&
iface.getIfAdminStatus().equals(SnmpMinimalPollInterface.IF_UP) &&
iface.getIfOperStatus() != null &&
iface.getIfOperStatus().equals(SnmpMinimalPollInterface.IF_DOWN) &&
iface.getIfOperStatus() != oldStatus) {
sendOperDownEvent(iface);
}
}
}
}
//Constructor
/**
* <p>Constructor for PollableSnmpInterface.</p>
*
* @param parent a {@link org.opennms.netmgt.snmpinterfacepoller.pollable.PollableInterface} object.
*/
public PollableSnmpInterface(
PollableInterface parent) {
m_parent = parent;
m_snmpinterfaces = new HashMap<Integer,OnmsSnmpInterface>();
}
/**
* <p>getSchedule</p>
*
* @return a {@link org.opennms.netmgt.scheduler.Schedule} object.
*/
public Schedule getSchedule() {
return m_schedule;
}
/**
* <p>setSchedule</p>
*
* @param schedule a {@link org.opennms.netmgt.scheduler.Schedule} object.
*/
public void setSchedule(Schedule schedule) {
m_schedule = schedule;
}
/**
* <p>getSnmppollableconfig</p>
*
* @return a {@link org.opennms.netmgt.snmpinterfacepoller.pollable.PollableSnmpInterfaceConfig} object.
*/
public PollableSnmpInterfaceConfig getSnmppollableconfig() {
return m_snmppollableconfig;
}
/**
* <p>setSnmppollableconfig</p>
*
* @param snmppollableconfig a {@link org.opennms.netmgt.snmpinterfacepoller.pollable.PollableSnmpInterfaceConfig} object.
*/
public void setSnmppollableconfig(
PollableSnmpInterfaceConfig snmppollableconfig) {
m_snmppollableconfig = snmppollableconfig;
}
/**
* <p>getParent</p>
*
* @return a {@link org.opennms.netmgt.snmpinterfacepoller.pollable.PollableInterface} object.
*/
public PollableInterface getParent() {
return m_parent;
}
/**
* <p>getContext</p>
*
* @return a {@link org.opennms.netmgt.snmpinterfacepoller.pollable.PollContext} object.
*/
public PollContext getContext() {
return getParent().getContext();
}
/**
* <p>getName</p>
*
* @return a {@link java.lang.String} object.
*/
public String getName() {
return m_name;
}
/**
* <p>setName</p>
*
* @param name a {@link java.lang.String} object.
*/
public void setName(String name) {
m_name = name;
}
/**
* <p>isReady</p>
*
* @return a boolean.
*/
public boolean isReady() {
return true;
}
/**
* <p>run</p>
*/
public void run() {
if (getParent().polling()) {
log().info("run: polling SNMP interfaces on package/interface " + getParent().getPackageName()+ "/" + getName() + "on primary address: " + getParent().getIpaddress());
if (m_snmpinterfaces == null || m_snmpinterfaces.isEmpty()) {
log().debug("No Interface found. Doing nothing");
} else {
log().debug(m_snmpinterfaces.size() + " Interfaces found. Getting Statutes....");
SnmpPollInterfaceMonitor pollMonitor = new SnmpPollInterfaceMonitor();
int maxiface = getMaxInterfacePerPdu();
if (maxiface == 0) maxiface=m_snmpinterfaces.size();
log().debug("Max Interface Per Pdu is: " + maxiface);
List<SnmpMinimalPollInterface> mifaces = getSnmpMinimalPollInterface();
int start =0;
while (start + maxiface< m_snmpinterfaces.size()) {
doPoll(pollMonitor,mifaces.subList(start, start+maxiface));
start += maxiface;
}
doPoll(pollMonitor,mifaces.subList(start, m_snmpinterfaces.size()));
}
} else {
log().info("not polling: " + getParent().getIpaddress());
} // End if polling
} //end Run method
private void doPoll(SnmpPollInterfaceMonitor pollMonitor, List<SnmpMinimalPollInterface> mifaces) {
log().info("doPoll: input interfaces number: " + mifaces.size());
mifaces = pollMonitor.poll(getAgentConfig(), mifaces);
boolean refresh = false;
Date now = getDate();
if (mifaces != null) {
log().info("doPoll: PollerMonitor return interfaces number: " + mifaces.size());
for (SnmpMinimalPollInterface miface : mifaces) {
log().debug("Working on interface with ifindex: " + miface.getIfindex());
log().debug("Interface PollStatus is " + miface.getStatus().getStatusName());
if (miface.getStatus().isUp()) {
OnmsSnmpInterface iface = m_snmpinterfaces.get(new Integer(miface.getIfindex()));
log().debug("Previuos status Admin/Oper: " + iface.getIfAdminStatus() + "/" + iface.getIfOperStatus());
log().debug("Current status Admin/Oper: " + miface.getAdminstatus() + "/" + miface.getOperstatus());
// If the interface is Admin Up, and the interface is Operational Down, we generate an alarm.
if ( miface.getAdminstatus() == SnmpMinimalPollInterface.IF_UP
&& iface.getIfAdminStatus() == SnmpMinimalPollInterface.IF_UP
&& miface.getOperstatus() == SnmpMinimalPollInterface.IF_DOWN
&& iface.getIfOperStatus() == SnmpMinimalPollInterface.IF_UP) {
sendOperDownEvent(iface);
}
// If the interface is Admin Up, and the interface is Operational Up, we generate a clean alarm
// if was previuos down in alarm table
if ( miface.getAdminstatus() == SnmpMinimalPollInterface.IF_UP
&& iface.getIfAdminStatus() == SnmpMinimalPollInterface.IF_UP
&& miface.getOperstatus() == SnmpMinimalPollInterface.IF_UP
&& iface.getIfOperStatus() == SnmpMinimalPollInterface.IF_DOWN ) {
sendOperUpEvent(iface);
}
if ( miface.getAdminstatus() == SnmpMinimalPollInterface.IF_DOWN
&& iface.getIfAdminStatus() == SnmpMinimalPollInterface.IF_UP) {
sendAdminDownEvent(iface);
}
if ( miface.getAdminstatus() == SnmpMinimalPollInterface.IF_UP
&& iface.getIfAdminStatus() == SnmpMinimalPollInterface.IF_DOWN
&& miface.getOperstatus() != SnmpMinimalPollInterface.IF_UP) {
sendAdminUpEvent(iface);
}
if ( miface.getAdminstatus() == SnmpMinimalPollInterface.IF_UP
&& iface.getIfAdminStatus() == SnmpMinimalPollInterface.IF_DOWN
&& miface.getOperstatus() == SnmpMinimalPollInterface.IF_UP) {
sendAdminUpEvent(iface);
sendOperUpEvent(iface);
}
iface.setIfAdminStatus(new Integer(miface.getAdminstatus()));
iface.setIfOperStatus(new Integer(miface.getOperstatus()));
iface.setLastSnmpPoll(now);
// Save Data to Database
try {
update(iface);
} catch (Throwable e) {
log().warn("Failing updating Interface" + iface.getIfName()+" " + e.getLocalizedMessage());
refresh = true;
}
} else {
log().debug("No "+ getContext().getServiceName() + " data available for interface.");
} //End if status OK
} //end while on interface
if (refresh)
getParent().getParent().refresh(getParent().getNodeid());
} else {
log().error("the monitor return null object");
} //end If not null
}
private void update(OnmsSnmpInterface iface) {
getContext().update(iface);
}
private void sendAdminUpEvent(OnmsSnmpInterface iface) {
getContext().sendEvent(getContext().createEvent(EventConstants.SNMP_INTERFACE_ADMIN_UP_EVENT_UEI,
getParent().getNodeid(), getParent().getIpaddress(), getDate(), iface));
}
private void sendAdminDownEvent(OnmsSnmpInterface iface) {
getContext().sendEvent(getContext().createEvent(EventConstants.SNMP_INTERFACE_ADMIN_DOWN_EVENT_UEI,
getParent().getNodeid(), getParent().getIpaddress(), getDate(), iface));
}
private void sendOperUpEvent(OnmsSnmpInterface iface) {
getContext().sendEvent(getContext().createEvent(EventConstants.SNMP_INTERFACE_OPER_UP_EVENT_UEI,
getParent().getNodeid(), getParent().getIpaddress(), getDate(), iface));
}
private void sendOperDownEvent(OnmsSnmpInterface iface) {
getContext().sendEvent(getContext().createEvent(EventConstants.SNMP_INTERFACE_OPER_DOWN_EVENT_UEI,
getParent().getNodeid(), getParent().getIpaddress(), getDate(), iface));
}
private Date getDate() {
return new Date();
}
private SnmpMinimalPollInterface getMinimalFromOnmsSnmpInterface(OnmsSnmpInterface iface) {
int adminStatus = SnmpMinimalPollInterface.IF_UP;
int operStatus = SnmpMinimalPollInterface.IF_UP;
if (iface.getIfAdminStatus() != null) {
adminStatus = iface.getIfAdminStatus().intValue();
} else {
iface.setIfAdminStatus(SnmpMinimalPollInterface.IF_UNKNOWN);
}
if (iface.getIfOperStatus() != null) {
operStatus = iface.getIfOperStatus().intValue();
} else {
iface.setIfOperStatus(SnmpMinimalPollInterface.IF_UNKNOWN);
}
return new SnmpMinimalPollInterface(iface.getIfIndex().intValue(),adminStatus, operStatus);
}
private List<SnmpMinimalPollInterface> getSnmpMinimalPollInterface() {
List<SnmpMinimalPollInterface> mifaces = new ArrayList<SnmpMinimalPollInterface>();
for (OnmsSnmpInterface iface: getSnmpinterfaces()) {
mifaces.add(getMinimalFromOnmsSnmpInterface(iface));
}
return mifaces;
}
/**
* <p>schedule</p>
*/
public void schedule() {
if (m_schedule == null)
throw new IllegalStateException("Cannot schedule a service whose schedule is set to null");
m_schedule.schedule();
}
/**
* <p>delete</p>
*/
protected void delete() {
m_schedule.unschedule();
}
private ThreadCategory log() {
return ThreadCategory.getInstance(PollableSnmpInterface.class);
}
/**
* <p>getAgentConfig</p>
*
* @return a {@link org.opennms.netmgt.snmp.SnmpAgentConfig} object.
*/
public SnmpAgentConfig getAgentConfig() {
return m_agentConfig;
}
/**
* <p>setAgentConfig</p>
*
* @param config a {@link org.opennms.netmgt.snmp.SnmpAgentConfig} object.
*/
public void setAgentConfig(SnmpAgentConfig config) {
m_agentConfig = config;
}
/**
* <p>getCriteria</p>
*
* @return a {@link java.lang.String} object.
*/
public String getCriteria() {
return m_criteria;
}
/**
* <p>setCriteria</p>
*
* @param m_criteria a {@link java.lang.String} object.
*/
public void setCriteria(String m_criteria) {
this.m_criteria = m_criteria;
}
/**
* <p>Getter for the field <code>maxInterfacePerPdu</code>.</p>
*
* @return a int.
*/
public int getMaxInterfacePerPdu() {
return getAgentConfig().getMaxVarsPerPdu();
}
}