package org.infosec.ismp.poller;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.sql.SQLException;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.infosec.ismp.eventd.EventIpcManager;
import org.infosec.ismp.model.event.Event;
import org.infosec.ismp.model.event.EventBuilder;
import org.infosec.ismp.model.event.EventConstants;
import org.infosec.ismp.model.event.EventListener;
import org.infosec.ismp.model.poller.IcmpPlugin;
import org.infosec.ismp.poller.pollable.PendingPollEvent;
import org.infosec.ismp.poller.pollable.PollContext;
import org.infosec.ismp.poller.pollable.PollEvent;
import org.infosec.ismp.poller.pollable.PollableService;
import org.infosec.ismp.util.ThreadCategory;
/**
* Represents a DefaultPollContext
*
*/
public class DefaultPollContext implements PollContext, EventListener {
private volatile PollerConfig m_pollerConfig;
private volatile QueryManager m_queryManager;
private volatile EventIpcManager m_eventManager;
private volatile String m_name;
private volatile String m_localHostName;
private volatile boolean m_listenerAdded = false;
private final List<PendingPollEvent> m_pendingPollEvents = new LinkedList<PendingPollEvent>();
public EventIpcManager getEventManager() {
return m_eventManager;
}
public void setEventManager(EventIpcManager eventManager) {
m_eventManager = eventManager;
}
public void setLocalHostName(String localHostName) {
m_localHostName = localHostName;
}
public String getLocalHostName() {
return m_localHostName;
}
@Override
public String getName() {
return m_name;
}
public void setName(String name) {
m_name = name;
}
public PollerConfig getPollerConfig() {
return m_pollerConfig;
}
public void setPollerConfig(PollerConfig pollerConfig) {
m_pollerConfig = pollerConfig;
}
public QueryManager getQueryManager() {
return m_queryManager;
}
public void setQueryManager(QueryManager queryManager) {
m_queryManager = queryManager;
}
/* (non-Javadoc)
* @see org.opennms.netmgt.poller.pollables.PollContext#getCriticalServiceName()
*/
@Override
public String getCriticalServiceName() {
return getPollerConfig().getCriticalService();
}
/* (non-Javadoc)
* @see org.opennms.netmgt.poller.pollables.PollContext#isNodeProcessingEnabled()
*/
@Override
public boolean isNodeProcessingEnabled() {
return getPollerConfig().nodeOutageProcessingEnabled();
}
/* (non-Javadoc)
* @see org.opennms.netmgt.poller.pollables.PollContext#isPollingAllIfCritServiceUndefined()
*/
@Override
public boolean isPollingAllIfCritServiceUndefined() {
return getPollerConfig().pollAllIfNoCriticalServiceDefined();
}
/* (non-Javadoc)
* @see org.opennms.netmgt.poller.pollables.PollContext#sendEvent(org.opennms.netmgt.xml.event.Event)
*/
@Override
public PollEvent sendEvent(Event event) {
if (!m_listenerAdded) {
getEventManager().addEventListener(this);
m_listenerAdded = true;
}
PendingPollEvent pollEvent = new PendingPollEvent(event);
synchronized (m_pendingPollEvents) {
m_pendingPollEvents.add(pollEvent);
}
// log().info("Sending "+event.getUei()+" for element "+event.getNodeid()+":"+event.getInterface()+":"+event.getService(),
// new Exception("StackTrace"));
getEventManager().sendNow(event);
return pollEvent;
}
ThreadCategory log() {
return ThreadCategory.getInstance(getClass());
}
@Override
public Event createEvent(String uei, int nodeId, InetAddress address,
String svcName, Date date, String reason) {
ThreadCategory log = ThreadCategory.getInstance(this.getClass());
if (log.isDebugEnabled())
log.debug("createEvent: uei = " + uei + " nodeid = " + nodeId);
EventBuilder bldr = new EventBuilder(uei, this.getName(), date);
bldr.setNodeid(nodeId);
if (address != null) {
bldr.setInterface(address.getHostAddress());
}
if (svcName != null) {
bldr.setService(svcName);
}
bldr.setHost(this.getLocalHostName());
if (uei.equals(EventConstants.NODE_DOWN_EVENT_UEI)
&& this.getPollerConfig().pathOutageEnabled()) {
String[] criticalPath = this.getQueryManager().getCriticalPath(
nodeId);
if (criticalPath[0] != null && !criticalPath[0].equals("")) {
if (!this.testCriticalPath(criticalPath)) {
log.debug("Critical path test failed for node " + nodeId);
bldr.addParam(EventConstants.PARM_LOSTSERVICE_REASON,
EventConstants.PARM_VALUE_PATHOUTAGE);
bldr.addParam(EventConstants.PARM_CRITICAL_PATH_IP,
criticalPath[0]);
bldr.addParam(EventConstants.PARM_CRITICAL_PATH_SVC,
criticalPath[1]);
} else {
log.debug("Critical path test passed for node " + nodeId);
}
} else {
log.debug("No Critical path to test for node " + nodeId);
}
}
if (uei.equals(EventConstants.NODE_LOST_SERVICE_EVENT_UEI)) {
bldr.addParam(EventConstants.PARM_LOSTSERVICE_REASON,
(reason == null ? "Unknown" : reason));
}
// For node level events (nodeUp/nodeDown) retrieve the
// node's nodeLabel value and add it as a parm
if (uei.equals(EventConstants.NODE_UP_EVENT_UEI)
|| uei.equals(EventConstants.NODE_DOWN_EVENT_UEI)) {
String nodeLabel = this.getNodeLabel(nodeId);
bldr.addParam(EventConstants.PARM_NODE_LABEL, nodeLabel);
}
return bldr.getEvent();
}
@Override
public void openOutage(final PollableService svc,
final PollEvent svcLostEvent) {
log().debug(
"openOutage: Opening outage for: " + svc + " with event:"
+ svcLostEvent);
final int nodeId = svc.getNodeId();
final String ipAddr = svc.getIpAddr();
final String svcName = svc.getSvcName();
Runnable r = new Runnable() {
@Override
public void run() {
log().debug(
"run: Opening outage with query manager: " + svc
+ " with event:" + svcLostEvent);
getQueryManager().openOutage(
getPollerConfig().getNextOutageIdSql(), nodeId, ipAddr,
svcName, svcLostEvent.getEventId(),
EventConstants.formatToString(svcLostEvent.getDate()));
}
};
if (svcLostEvent instanceof PendingPollEvent) {
((PendingPollEvent) svcLostEvent).addPending(r);
} else {
r.run();
}
}
/* (non-Javadoc)
* @see org.opennms.netmgt.poller.pollables.PollContext#resolveOutage(org.opennms.netmgt.poller.pollables.PollableService, org.opennms.netmgt.xml.event.Event)
*/
@Override
public void resolveOutage(PollableService svc,
final PollEvent svcRegainEvent) {
final int nodeId = svc.getNodeId();
final String ipAddr = svc.getIpAddr();
final String svcName = svc.getSvcName();
Runnable r = new Runnable() {
@Override
public void run() {
getQueryManager()
.resolveOutage(
nodeId,
ipAddr,
svcName,
svcRegainEvent.getEventId(),
EventConstants.formatToString(svcRegainEvent
.getDate()));
}
};
if (svcRegainEvent instanceof PendingPollEvent) {
((PendingPollEvent) svcRegainEvent).addPending(r);
} else {
r.run();
}
}
@Override
public void reparentOutages(String ipAddr, int oldNodeId, int newNodeId) {
getQueryManager().reparentOutages(ipAddr, oldNodeId, newNodeId);
}
/* (non-Javadoc)
* @see org.opennms.netmgt.poller.pollables.PollContext#isServiceUnresponsiveEnabled()
*/
@Override
public boolean isServiceUnresponsiveEnabled() {
return getPollerConfig().serviceUnresponsiveEnabled();
}
/* (non-Javadoc)
* @see org.opennms.netmgt.eventd.EventListener#onEvent(org.opennms.netmgt.xml.event.Event)
*/
@Override
public void onEvent(Event e) {
synchronized (m_pendingPollEvents) {
log().debug(
"onEvent: Received event: " + e + " uei: " + e.getUei()
+ ", dbid: " + e.getUuid());
for (Iterator<PendingPollEvent> it = m_pendingPollEvents.iterator(); it
.hasNext();) {
PendingPollEvent pollEvent = it.next();
log().debug(
"onEvent: comparing events to poll event: " + pollEvent);
if (e.equals(pollEvent.getEvent())) {
log().debug("onEvent: completing pollevent: " + pollEvent);
pollEvent.complete(e);
}
}
for (Iterator<PendingPollEvent> it = m_pendingPollEvents.iterator(); it
.hasNext();) {
PendingPollEvent pollEvent = it.next();
log().debug(
"onEvent: determining if pollEvent is pending: "
+ pollEvent);
if (pollEvent.isPending())
continue;
log().debug(
"onEvent: processing pending pollEvent...: "
+ pollEvent);
pollEvent.processPending();
it.remove();
log().debug(
"onEvent: processing of pollEvent completed.: "
+ pollEvent);
}
}
}
boolean testCriticalPath(String[] criticalPath) {
// TODO: Generalize the service
InetAddress addr = null;
boolean result = true;
ThreadCategory log = log();
log.debug("Test critical path IP " + criticalPath[0]);
try {
addr = InetAddress.getByName(criticalPath[0]);
} catch (UnknownHostException e) {
log.error("failed to convert string address to InetAddress "
+ criticalPath[0]);
return true;
}
IcmpPlugin p = new IcmpPlugin();
Map<String, Object> map = new HashMap<String, Object>();
// map.put("retry", new Long(OpennmsServerConfigFactory.getInstance()
// .getDefaultCriticalPathRetries()));
// map.put("timeout", new Long(OpennmsServerConfigFactory.getInstance()
// .getDefaultCriticalPathTimeout()));
result = p.isProtocolSupported(addr, map);
return result;
}
String getNodeLabel(int nodeId) {
String nodeLabel = null;
try {
nodeLabel = getQueryManager().getNodeLabel(nodeId);
} catch (SQLException sqlE) {
// Log a warning
log().warn("Failed to retrieve node label for nodeid " + nodeId,
sqlE);
}
if (nodeLabel == null) {
// This should never happen but if it does just
// use nodeId for the nodeLabel so that the
// event description has something to display.
nodeLabel = String.valueOf(nodeId);
}
return nodeLabel;
}
}