//
// This file is part of the OpenNMS(R) Application.
//
// OpenNMS(R) is Copyright (C) 2002-2006 The OpenNMS Group, Inc. All rights reserved.
// OpenNMS(R) is a derivative work, containing both original code, included code and modified
// code that was published under the GNU General Public License. Copyrights for modified
// and included code are below.
//
// OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc.
//
// Modifications:
//
// 2009 May 14: added threshold config change handler for in-line thresholds processing
// 2006 Apr 27: added support for pathOutageEnabled
// 2006 Apr 17: added path outage processing for nodeDown event
// 2003 Nov 11: Merged changes from Rackspace project
// 2003 Oct 08: Implemented the poller release function.
// 2003 Jan 31: Cleaned up some unused imports.
//
// Original code base Copyright (C) 1999-2001 Oculan Corp. All rights reserved.
//
// This program 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 2 of the License, or
// (at your option) any later version.
//
// This program 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 this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
// For more information contact:
// OpenNMS Licensing <license@opennms.org>
// http://www.opennms.org/
// http://www.opennms.com/
//
package org.infosec.ismp.poller;
import java.lang.reflect.UndeclaredThrowableException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;
import java.util.concurrent.atomic.AtomicInteger;
import javax.sql.DataSource;
import org.infosec.ismp.daemon.AbstractServiceDaemon;
import org.infosec.ismp.eventd.EventIpcManager;
import org.infosec.ismp.model.poller.PollStatus;
import org.infosec.ismp.model.poller.ServiceMonitor;
import org.infosec.ismp.poller.pollable.PollEvent;
import org.infosec.ismp.poller.pollable.PollableNetwork;
import org.infosec.ismp.poller.pollable.PollableNode;
import org.infosec.ismp.poller.pollable.PollableService;
import org.infosec.ismp.poller.pollable.PollableServiceConfig;
import org.infosec.ismp.util.Querier;
import org.infosec.ismp.util.ThreadCategory;
import org.infosec.ismp.util.scheduler.LegacyScheduler;
import org.infosec.ismp.util.scheduler.Schedule;
import org.infosec.ismp.util.scheduler.Scheduler;
public class Poller extends AbstractServiceDaemon {
private final static Poller m_singleton = new Poller();
private boolean m_initialized = false;
private LegacyScheduler m_scheduler = null;
private PollerEventProcessor m_eventProcessor;
private PollableNetwork m_network;
private QueryManager m_queryManager;
private PollerConfig m_pollerConfig;
private EventIpcManager m_eventMgr;
private DataSource m_dataSource;
public Poller() {
super("ISMP.Poller");
}
/* Getters/Setters used for dependency injection */
public void setDataSource(DataSource dataSource) {
m_dataSource = dataSource;
}
public EventIpcManager getEventManager() {
return m_eventMgr;
}
public void setEventManager(EventIpcManager eventMgr) {
m_eventMgr = eventMgr;
}
public PollerEventProcessor getEventProcessor() {
return m_eventProcessor;
}
public void setEventProcessor(PollerEventProcessor eventProcessor) {
m_eventProcessor = eventProcessor;
}
public PollableNetwork getNetwork() {
return m_network;
}
public void setNetwork(PollableNetwork network) {
m_network = network;
}
public void setQueryManager(QueryManager queryManager) {
m_queryManager = queryManager;
}
public QueryManager getQueryManager() {
return m_queryManager;
}
public PollerConfig getPollerConfig() {
return m_pollerConfig;
}
public void setPollerConfig(PollerConfig pollerConfig) {
m_pollerConfig = pollerConfig;
}
public Scheduler getScheduler() {
return m_scheduler;
}
public void setScheduler(LegacyScheduler scheduler) {
m_scheduler = scheduler;
}
@Override
protected void onInit() {
// serviceUnresponsive behavior enabled/disabled?
log().debug(
"init: serviceUnresponsive behavior: "
+ (getPollerConfig().serviceUnresponsiveEnabled() ? "enabled"
: "disabled"));
createScheduler();
// try {
// log().debug("init: Closing outages for unmanaged services");
//
// closeOutagesForUnmanagedServices();
// } catch (Exception e) {
// log().error("init: Failed to close ouates for unmanage services", e);
// }
// Schedule the interfaces currently in the database
//
try {
log().debug("start: Scheduling existing interfaces");
scheduleExistingServices();
} catch (Exception sqlE) {
log().error("start: Failed to schedule existing interfaces", sqlE);
}
// Create an event receiver. The receiver will
// receive events, process them, creates network
// interfaces, and schedulers them.
//
try {
log().debug("start: Creating event broadcast event processor");
setEventProcessor(new PollerEventProcessor(this));
} catch (Throwable t) {
log().fatal(
"start: Failed to initialized the broadcast event receiver",
t);
throw new UndeclaredThrowableException(t);
}
m_initialized = true;
}
// /**
// *
// */
// private void closeOutagesForUnmanagedServices() {
// Timestamp closeTime = new Timestamp((new java.util.Date()).getTime());
//
// final String DB_CLOSE_OUTAGES_FOR_UNMANAGED_SERVICES =
// "UPDATE outages set ifregainedservice = ? where outageid in (select outages.outageid from outages, ifservices where ((outages.nodeid = ifservices.nodeid) AND (outages.ipaddr = ifservices.ipaddr) AND (outages.serviceid = ifservices.serviceid) AND ((ifservices.status = 'D') OR (ifservices.status = 'F') OR (ifservices.status = 'U')) AND (outages.ifregainedservice IS NULL)))";
// Updater svcUpdater = new Updater(m_dataSource,
// DB_CLOSE_OUTAGES_FOR_UNMANAGED_SERVICES);
// svcUpdater.execute(closeTime);
//
// final String DB_CLOSE_OUTAGES_FOR_UNMANAGED_INTERFACES =
// "UPDATE outages set ifregainedservice = ? where outageid in (select outages.outageid from outages, ipinterface where ((outages.nodeid = ipinterface.nodeid) AND (outages.ipaddr = ipinterface.ipaddr) AND ((ipinterface.ismanaged = 'F') OR (ipinterface.ismanaged = 'U')) AND (outages.ifregainedservice IS NULL)))";
// Updater ifUpdater = new Updater(m_dataSource,
// DB_CLOSE_OUTAGES_FOR_UNMANAGED_INTERFACES);
// ifUpdater.execute(closeTime);
//
// }
// public void closeOutagesForNode(Date closeDate, int eventId, int nodeId)
// {
// Timestamp closeTime = new Timestamp(closeDate.getTime());
// final String DB_CLOSE_OUTAGES_FOR_NODE =
// "UPDATE outages set ifregainedservice = ?, svcRegainedEventId = ? where outages.nodeId = ? AND (outages.ifregainedservice IS NULL)";
// Updater svcUpdater = new Updater(m_dataSource,
// DB_CLOSE_OUTAGES_FOR_NODE);
// svcUpdater
// .execute(closeTime, new Integer(eventId), new Integer(nodeId));
// }
//
// public void closeOutagesForInterface(Date closeDate, int eventId,
// int nodeId, String ipAddr) {
// Timestamp closeTime = new Timestamp(closeDate.getTime());
// final String DB_CLOSE_OUTAGES_FOR_IFACE =
// "UPDATE outages set ifregainedservice = ?, svcRegainedEventId = ? where outages.nodeId = ? AND outages.ipAddr = ? AND (outages.ifregainedservice IS NULL)";
// Updater svcUpdater = new Updater(m_dataSource,
// DB_CLOSE_OUTAGES_FOR_IFACE);
// svcUpdater.execute(closeTime, new Integer(eventId),
// new Integer(nodeId), ipAddr);
// }
//
// public void closeOutagesForService(Date closeDate, int eventId, int
// nodeId,
// String ipAddr, String serviceName) {
// Timestamp closeTime = new Timestamp(closeDate.getTime());
// final String DB_CLOSE_OUTAGES_FOR_SERVICE =
// "UPDATE outages set ifregainedservice = ?, svcRegainedEventId = ? where outageid in (select outages.outageid from outages, service where outages.nodeid = ? AND outages.ipaddr = ? AND outages.serviceid = service.serviceId AND service.servicename = ? AND outages.ifregainedservice IS NULL)";
// Updater svcUpdater = new Updater(m_dataSource,
// DB_CLOSE_OUTAGES_FOR_SERVICE);
// svcUpdater.execute(closeTime, new Integer(eventId),
// new Integer(nodeId), ipAddr, serviceName);
// }
private void createScheduler() {
ThreadCategory log = ThreadCategory.getInstance(getClass());
// Create a scheduler
//
try {
log.debug("init: Creating poller scheduler");
setScheduler(new LegacyScheduler("Poller", getPollerConfig()
.getThreads()));
} catch (RuntimeException e) {
log.fatal("init: Failed to create poller scheduler", e);
throw e;
}
}
@Override
protected void onStart() {
// get the category logger
// start the scheduler
//
try {
if (log().isDebugEnabled())
log().debug("start: Starting poller scheduler");
getScheduler().start();
} catch (RuntimeException e) {
if (log().isEnabledFor(ThreadCategory.Level.FATAL))
log().fatal("start: Failed to start scheduler", e);
throw e;
}
}
@Override
protected void onStop() {
if (getScheduler() != null) {
getScheduler().stop();
}
if (getEventProcessor() != null) {
getEventProcessor().close();
}
releaseServiceMonitors();
setScheduler(null);
}
private void releaseServiceMonitors() {
getPollerConfig().releaseAllServiceMonitors();
}
@Override
protected void onPause() {
getScheduler().pause();
}
@Override
protected void onResume() {
getScheduler().resume();
}
public static Poller getInstance() {
return m_singleton;
}
public ServiceMonitor getServiceMonitor(String svcName) {
return getPollerConfig().getServiceMonitor(svcName);
}
private void scheduleExistingServices() throws Exception {
ThreadCategory log = ThreadCategory.getInstance(getClass());
scheduleMatchingServices(null);
getNetwork().recalculateStatus();
getNetwork().propagateInitialCause();
getNetwork().resetStatusChanged();
// Debug dump pollable network
//
// if (log.isDebugEnabled()) {
// log.debug("scheduleExistingServices: dumping content of pollable network: ");
// getNetwork().dump();
// }
}
public void scheduleService(final int nodeId, final String nodeLabel,
final String ipAddr, final String svcName) {
final ThreadCategory log = ThreadCategory.getInstance(getClass());
try {
/*
* Do this here so that we can use the treeLock for this node as we
* add its service and schedule it
*/
PollableNode node;
synchronized (getNetwork()) {
node = getNetwork().getNode(nodeId);
if (node == null) {
node = getNetwork().createNode(nodeId, nodeLabel);
}
}
final PollableNode svcNode = node;
Runnable r = new Runnable() {
@Override
public void run() {
int matchCount = scheduleMatchingServices("ifServices.nodeId = "
+ nodeId
+ " AND ifServices.ipAddr = '"
+ ipAddr
+ "' AND service.serviceName = '" + svcName + "'");
if (matchCount > 0) {
svcNode.recalculateStatus();
svcNode.processStatusChange(new Date());
} else {
log.warn("Attempt to schedule service " + nodeId + "/"
+ ipAddr + "/" + svcName
+ " found no active service");
}
}
};
node.withTreeLock(r);
} catch (Exception e) {
log.error("Unable to schedule service " + nodeId + "/" + ipAddr
+ "/" + svcName, e);
}
}
private int scheduleMatchingServices(String criteria) {
// String sql =
// "SELECT ifServices.nodeId AS nodeId, node.nodeLabel AS nodeLabel, ifServices.ipAddr AS ipAddr, "
// +
// "ifServices.serviceId AS serviceId, service.serviceName AS serviceName, ifServices.status as status, "
// +
// "outages.svcLostEventId AS svcLostEventId, events.eventUei AS svcLostEventUei, "
// +
// "outages.ifLostService AS ifLostService, outages.ifRegainedService AS ifRegainedService "
// + "FROM ifServices "
// + "JOIN node ON ifServices.nodeId = node.nodeId "
// + "JOIN service ON ifServices.serviceId = service.serviceId "
// + "LEFT OUTER JOIN outages ON "
// + "ifServices.nodeId = outages.nodeId AND "
// + "ifServices.ipAddr = outages.ipAddr AND "
// + "ifServices.serviceId = outages.serviceId AND "
// + "ifRegainedService IS NULL "
// +
// "LEFT OUTER JOIN events ON outages.svcLostEventId = events.eventid "
// + "WHERE ifServices.status in ('A','N')"
// + (criteria == null ? "" : " AND " + criteria);
// TODO : 从数据库中获得需要轮询的服务的相关参数
final AtomicInteger count = new AtomicInteger(0);
String sql = "";
Querier querier = new Querier(m_dataSource, sql) {
@Override
public void processRow(ResultSet rs) throws SQLException {
if (scheduleService(rs.getInt("nodeId"),
rs.getString("nodeLabel"), rs.getString("ipAddr"),
rs.getString("serviceName"),
"A".equals(rs.getString("status")),
(Number) rs.getObject("svcLostEventId"),
rs.getTimestamp("ifLostService"),
rs.getString("svcLostEventUei"))) {
count.incrementAndGet();
}
}
};
querier.execute();
return count.get();
}
private void updateServiceStatus(int nodeId, String ipAddr,
String serviceName, String status) {
// TODO 更新被监控服务的状态
// final String sql = "UPDATE ifservices SET status = ? WHERE id "
// +
// " IN (SELECT ifs.id FROM ifservices AS ifs JOIN service AS svc ON ifs.serviceid = svc.serviceid "
// +
// " WHERE ifs.nodeId = ? AND ifs.ipAddr = ? AND svc.servicename = ?)";
// Updater updater = new Updater(m_dataSource, sql);
// updater.execute(status, nodeId, ipAddr, serviceName);
}
private boolean scheduleService(int nodeId, String nodeLabel,
String ipAddr, String serviceName, boolean active,
Number svcLostEventId, Date date, String svcLostUei) {
ThreadCategory log = ThreadCategory.getInstance(getClass());
// Package pkg = findPackageForService(ipAddr, serviceName);
// if (pkg == null) {
// if (active) {
// log.warn("Active service "
// + serviceName
// + " on "
// + ipAddr
// + " not configured for any package. Marking as Not Polled.");
// updateServiceStatus(nodeId, ipAddr, serviceName, "N");
// }
// return false;
// } else if (!active) {
// log.info("Active service " + serviceName + " on " + ipAddr
// + " is now configured for any package. Marking as active.");
// updateServiceStatus(nodeId, ipAddr, serviceName, "A");
// }
ServiceMonitor monitor = m_pollerConfig.getServiceMonitor(serviceName);
if (monitor == null) {
log.info("Could not find service monitor associated with service "
+ serviceName);
return false;
}
InetAddress addr;
try {
addr = InetAddress.getByName(ipAddr);
} catch (UnknownHostException e) {
log.error("Could not convert " + ipAddr + " as an InetAddress "
+ ipAddr);
return false;
}
PollableService svc = getNetwork().createService(nodeId, nodeLabel,
addr, serviceName);
PollableServiceConfig pollConfig = new PollableServiceConfig(svc,
m_pollerConfig, getScheduler());
svc.setPollConfig(pollConfig);
synchronized (svc) {
if (svc.getSchedule() == null) {
Schedule schedule = new Schedule(svc, pollConfig,
getScheduler());
svc.setSchedule(schedule);
}
}
if (svcLostEventId == null)
if (svc.getParent().getStatus().isUnknown()) {
svc.updateStatus(PollStatus.up());
} else {
svc.updateStatus(svc.getParent().getStatus());
}
else {
svc.updateStatus(PollStatus.down());
PollEvent cause = new DbPollEvent(svcLostEventId.intValue(),
svcLostUei, date);
svc.setCause(cause);
}
svc.schedule();
return true;
}
// private Package findPackageForService(String ipAddr, String serviceName)
// {
// Enumeration<Package> en = m_pollerConfig.enumeratePackage();
// Package lastPkg = null;
//
// while (en.hasMoreElements()) {
// Package pkg = en.nextElement();
// if (pollableServiceInPackage(ipAddr, serviceName, pkg))
// lastPkg = pkg;
// }
// return lastPkg;
// }
// protected boolean pollableServiceInPackage(String ipAddr,
// String serviceName, Package pkg) {
//
// if (pkg.getRemote()) {
// log().debug(
// "pollableServiceInPackage: this package: " + pkg.getName()
// + ", is a remote monitor package.");
// return false;
// }
//
// if (!m_pollerConfig.serviceInPackageAndEnabled(serviceName, pkg))
// return false;
//
// boolean inPkg = m_pollerConfig.interfaceInPackage(ipAddr, pkg);
//
// if (inPkg)
// return true;
//
// if (m_initialized) {
// m_pollerConfig.rebuildPackageIpListMap();
// return m_pollerConfig.interfaceInPackage(ipAddr, pkg);
// }
//
// return false;
// }
// public boolean packageIncludesIfAndSvc(Package pkg, String ipAddr,
// String svcName) {
// ThreadCategory log = ThreadCategory.getInstance(getClass());
//
// if (!getPollerConfig().serviceInPackageAndEnabled(svcName, pkg)) {
// if (log.isDebugEnabled())
// log.debug("packageIncludesIfAndSvc: address/service: "
// + ipAddr
// + "/"
// + svcName
// + " not scheduled, service is not enabled or does not exist in package: "
// + pkg.getName());
// return false;
// }
//
// // Is the interface in the package?
// //
// if (!getPollerConfig().interfaceInPackage(ipAddr, pkg)) {
//
// if (m_initialized) {
// getPollerConfig().rebuildPackageIpListMap();
// if (!getPollerConfig().interfaceInPackage(ipAddr, pkg)) {
// if (log.isDebugEnabled())
// log.debug("packageIncludesIfAndSvc: interface "
// + ipAddr + " gained service " + svcName
// + ", but the interface was not in package: "
// + pkg.getName());
// return false;
// }
// } else {
// if (log.isDebugEnabled())
// log.debug("packageIncludesIfAndSvc: address/service: "
// + ipAddr
// + "/"
// + svcName
// + " not scheduled, interface does not belong to package: "
// + pkg.getName());
// return false;
// }
// }
// return true;
// }
// public void refreshServicePackages() {
// PollableVisitor visitor = new PollableVisitorAdaptor() {
// @Override
// public void visitService(PollableService service) {
// service.refreshConfig();
// }
// };
// getNetwork().visit(visitor);
// }
//
// public void refreshServiceThresholds() {
// PollableVisitor visitor = new PollableVisitorAdaptor() {
// @Override
// public void visitService(PollableService service) {
// service.refreshThresholds();
// }
// };
// getNetwork().visit(visitor);
// }
}