/******************************************************************************* * This file is part of OpenNMS(R). * * Copyright (C) 2008-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.tl1d; import static org.opennms.core.utils.InetAddressUtils.addr; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import org.jfree.util.Log; import org.opennms.netmgt.EventConstants; import org.opennms.netmgt.config.tl1d.Tl1Element; import org.opennms.netmgt.daemon.AbstractServiceDaemon; import org.opennms.netmgt.dao.Tl1ConfigurationDao; import org.opennms.netmgt.model.events.EventBuilder; import org.opennms.netmgt.model.events.EventForwarder; import org.opennms.netmgt.model.events.annotations.EventHandler; import org.opennms.netmgt.model.events.annotations.EventListener; import org.opennms.netmgt.xml.event.Event; import org.opennms.netmgt.xml.event.Parm; /** * OpenNMS TL1 Daemon! * * @author <a href="mailto:david@opennms.org">David Hustace</a> * @version $Id: $ */ @EventListener(name="OpenNMS:Tl1d") public class Tl1d extends AbstractServiceDaemon { /* * The last status sent to the service control manager. */ private volatile int m_status = START_PENDING; private volatile Thread m_tl1MesssageProcessor; private volatile EventForwarder m_eventForwarder; private volatile Tl1ConfigurationDao m_configurationDao; private final BlockingQueue<Tl1AutonomousMessage> m_tl1Queue = new LinkedBlockingQueue<Tl1AutonomousMessage>(); private final List<Tl1Client> m_tl1Clients = new ArrayList<Tl1Client>(); /** * <p>Constructor for Tl1d.</p> */ public Tl1d() { super("OpenNMS.Tl1d"); } /** * <p>handleRelooadConfigurationEvent</p> * * @param e a {@link org.opennms.netmgt.xml.event.Event} object. */ @EventHandler(uei=EventConstants.RELOAD_DAEMON_CONFIG_UEI) public void handleRelooadConfigurationEvent(Event e) { if (isReloadConfigEventTarget(e)) { EventBuilder ebldr = null; try { stopListeners(); removeClients(); /* * leave everything currently on the queue, no need to mess with that, might want a handler * someday for emptying the current queue on a reload event or even a pause clients or something. * * Don't interrupt message processor, it simply waits on the queue from something to be added. * */ m_configurationDao.update(); initializeTl1Connections(); startClients(); log().debug("handleReloadConfigurationEvent: "+m_tl1Clients.size()+" defined."); log().info("handleReloadConfigurationEvent: completed."); ebldr = new EventBuilder(EventConstants.RELOAD_DAEMON_CONFIG_SUCCESSFUL_UEI, getName()); ebldr.addParam(EventConstants.PARM_DAEMON_NAME, "Tl1d"); } catch (Throwable exception) { log().error("handleReloadConfigurationEvent: failed.", exception); ebldr = new EventBuilder(EventConstants.RELOAD_DAEMON_CONFIG_FAILED_UEI, getName()); ebldr.addParam(EventConstants.PARM_DAEMON_NAME, "Tl1d"); ebldr.addParam(EventConstants.PARM_REASON, exception.getLocalizedMessage().substring(1, 128)); } if (ebldr != null) { m_eventForwarder.sendNow(ebldr.getEvent()); } } } private boolean isReloadConfigEventTarget(Event event) { boolean isTarget = false; List<Parm> parmCollection = event.getParmCollection(); for (Parm parm : parmCollection) { if (EventConstants.PARM_DAEMON_NAME.equals(parm.getParmName()) && "Tl1d".equalsIgnoreCase(parm.getValue().getContent())) { isTarget = true; break; } } log().debug("isReloadConfigEventTarget: Tl1d was target of reload event: "+isTarget); return isTarget; } /** * <p>onInit</p> */ public synchronized void onInit() { initializeTl1Connections(); } /** * <p>onStart</p> */ public synchronized void onStart() { log().info("onStart: Initializing Tl1d message processing." ); m_tl1MesssageProcessor = new Thread("Tl1-Message-Processor") { public void run() { doMessageProcessing(); } }; log().info("onStart: starting message processing thread..."); m_tl1MesssageProcessor.start(); log().info("onStart: message processing thread started."); startClients(); log().info("onStart: Finished Initializing Tl1d connections."); } private void startClients() { log().info("startClients: starting clients..."); for (Tl1Client client : m_tl1Clients) { log().debug("startClients: starting client: "+client); client.start(); log().debug("startClients: started client."); } log().info("startClients: clients started."); } /** * <p>onStop</p> */ public synchronized void onStop() { stopListeners(); m_tl1MesssageProcessor.interrupt(); removeClients(); } private void removeClients() { log().info("removeClients: removing current set of defined TL1 clients..."); Iterator<Tl1Client> it = m_tl1Clients.iterator(); while (it.hasNext()) { Tl1Client client = it.next(); log().debug("removeClients: removing client: "+client); client = null; it.remove(); } log().info("removeClients: all clients removed."); } private void stopListeners() { log().info("stopListeners: calling stop on all clients..."); for (Tl1Client client : m_tl1Clients) { log().debug("stopListeners: calling stop on client: "+client); client.stop(); } log().info("stopListeners: clients stopped."); } private void initializeTl1Connections() { log().info("onInit: Initializing Tl1d connections..." ); List<Tl1Element> configElements = m_configurationDao.getElements(); for(Tl1Element element : configElements) { try { Tl1Client client = (Tl1Client) Class.forName(element.getTl1ClientApi()).newInstance(); log().debug("initializeTl1Connections: initializing client: "+client); client.setHost(element.getHost()); client.setPort(element.getPort()); client.setTl1Queue(m_tl1Queue); client.setMessageProcessor((Tl1AutonomousMessageProcessor) Class.forName(element.getTl1MessageParser()).newInstance()); client.setLog(log()); client.setReconnectionDelay(element.getReconnectDelay()); m_tl1Clients.add(client); log().debug("initializeTl1Connections: client initialized."); } catch (InstantiationException e) { log().error("onInit: could not instantiate specified class.", e); } catch (IllegalAccessException e) { log().error("onInit: could not access specified class.", e); } catch (ClassNotFoundException e) { log().error("onInit: could not find specified class.", e); } } log().info("onInit: Finished Initializing Tl1d connections."); } private void processMessage(Tl1AutonomousMessage message) { log().debug("processMessage: Processing message: "+message); EventBuilder bldr = new EventBuilder(Tl1AutonomousMessage.UEI, "Tl1d"); bldr.setHost(message.getHost()); bldr.setInterface(addr(message.getHost())); //interface is the IP bldr.setService("TL-1"); //Service it TL-1 bldr.setSeverity(message.getId().getHighestSeverity()); bldr.setTime(message.getTimestamp()); bldr.addParam("raw-message", message.getRawMessage()); bldr.addParam("alarm-code", message.getId().getAlarmCode()); bldr.addParam("atag", message.getId().getAlarmTag()); bldr.addParam("verb", message.getId().getVerb()); bldr.addParam("autoblock", message.getAutoBlock().getBlock()); bldr.addParam("aid",message.getAutoBlock().getAid()); bldr.addParam("additionalParams",message.getAutoBlock().getAdditionalParams()); m_eventForwarder.sendNow(bldr.getEvent()); log().debug("processMessage: Message processed: "+ message); } /** * Returns the current status of the service. * * @return The service's status. */ public synchronized int getStatus() { return m_status; } private void doMessageProcessing() { log().debug("doMessageProcessing: Processing messages."); boolean cont = true; while (cont ) { try { log().debug("doMessageProcessing: taking message from queue.."); Tl1AutonomousMessage message = m_tl1Queue.take(); log().debug("doMessageProcessing: message taken: "+message); processMessage(message); } catch (InterruptedException e) { Log.warn("doMessageProcessing: received interrupt: "+e, e); } } log().debug("doMessageProcessing: Exiting processing messages."); } /** * <p>setEventForwarder</p> * * @param eventForwarder a {@link org.opennms.netmgt.model.events.EventForwarder} object. */ public void setEventForwarder(EventForwarder eventForwarder) { m_eventForwarder = eventForwarder; } /** * <p>getEventForwarder</p> * * @return a {@link org.opennms.netmgt.model.events.EventForwarder} object. */ public EventForwarder getEventForwarder() { return m_eventForwarder; } /** * <p>setConfigurationDao</p> * * @param configurationDao a {@link org.opennms.netmgt.dao.Tl1ConfigurationDao} object. */ public void setConfigurationDao(Tl1ConfigurationDao configurationDao) { m_configurationDao = configurationDao; } }