org.opennms.ng.services.trapd.Trapd.java Source code

Java tutorial

Introduction

Here is the source code for org.opennms.ng.services.trapd.Trapd.java

Source

/*******************************************************************************
 * This file is part of OpenNMS(R).
 *
 * Copyright (C) 2006-2012 The OpenNMS Group, Inc.
 * OpenNMS(R) is Copyright (C) 1999-2012 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.ng.services.trapd;

import java.io.IOException;
import java.lang.reflect.UndeclaredThrowableException;
import java.net.InetAddress;
import java.sql.SQLException;
import java.util.List;
import java.util.concurrent.ExecutorService;

import org.opennms.core.logging.Logging;
import org.opennms.core.utils.BeanUtils;
import org.opennms.core.utils.InetAddressUtils;
import org.opennms.netmgt.snmp.SnmpUtils;
import org.opennms.netmgt.snmp.SnmpV3User;
import org.opennms.netmgt.snmp.TrapNotification;
import org.opennms.netmgt.snmp.TrapNotificationListener;
import org.opennms.netmgt.snmp.TrapProcessor;
import org.opennms.netmgt.snmp.TrapProcessorFactory;
import org.opennms.netmgt.trapd.BroadcastEventProcessor;
import org.opennms.netmgt.trapd.EventCreator;
import org.opennms.netmgt.trapd.TrapdIpMgr;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;

/**
 * <p>
 * The Trapd listens for SNMP traps on the standard port(162). Creates a
 * SnmpTrapSession and implements the SnmpTrapHandler to get callbacks when
 * traps are received.
 * </p>
 * <p/>
 * <p>
 * The received traps are converted into XML and sent to eventd.
 * </p>
 * <p/>
 * <p>
 * <strong>Note: </strong>Trapd is a PausableFiber so as to receive control
 * events. However, a 'pause' on Trapd has no impact on the receiving and
 * processing of traps.
 * </p>
 *
 * @author <A HREF="mailto:weave@oculan.com">Brian Weaver </A>
 * @author <A HREF="mailto:sowmya@opennms.org">Sowmya Nataraj </A>
 * @author <A HREF="mailto:larry@opennms.org">Lawrence Karnowski </A>
 * @author <A HREF="mailto:mike@opennms.org">Mike Davidson </A>
 * @author <A HREF="mailto:tarus@opennms.org">Tarus Balog </A>
 * @author <A HREF="http://www.opennms.org">OpenNMS.org </A>
 */
public class Trapd implements TrapProcessorFactory, TrapNotificationListener {

    public static final int START_PENDING = 0;
    public static final int STARTING = 1;
    public static final int RUNNING = 2;
    public static final int STOP_PENDING = 3;
    public static final int STOPPED = 4;
    public static final int PAUSE_PENDING = 5;
    public static final int PAUSED = 6;
    public static final int RESUME_PENDING = 7;
    private static final Logger LOG = LoggerFactory.getLogger(Trapd.class);
    private static final String LOG4J_CATEGORY = "trapd";
    /**
     * The last status sent to the service control manager.
     */
    private int m_status = START_PENDING;
    /**
     * The thread pool that processes traps
     */
    private ExecutorService m_backlogQ;
    /**
     * The queue processing thread
     */
    private TrapQueueProcessorFactory m_processorFactory;
    /**
     * The class instance used to receive new events from for the system.
     */
    private BroadcastEventProcessor m_eventReader;
    /**
     * Trapd IP manager.  Contains IP address -> node ID mapping.
     */
    private TrapdIpMgr m_trapdIpMgr;
    private String m_snmpTrapAddress;
    private Integer m_snmpTrapPort;
    private List<SnmpV3User> m_snmpV3Users;
    private boolean m_registeredForTraps;

    /**
     * <p/>
     * Constructs a new Trapd object that receives and forwards trap messages
     * via JSDT. The session is initialized with the default client name of <EM>
     * OpenNMS.trapd</EM>. The trap session is started on the default port, as
     * defined by the SNMP library.
     * </P>
     *
     * @see org.opennms.protocols.snmp.SnmpTrapSession
     */
    public Trapd() {
        //  super(LOG4J_CATEGORY);
    }

    public static String getLoggingCategory() {
        return LOG4J_CATEGORY;
    }

    /**
     * <p>createTrapProcessor</p>
     *
     * @return a {@link org.opennms.netmgt.snmp.TrapProcessor} object.
     */
    @Override
    public TrapProcessor createTrapProcessor() {
        return new EventCreator(m_trapdIpMgr);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void trapReceived(TrapNotification trapNotification) {
        m_backlogQ.submit(m_processorFactory.getInstance(trapNotification));
    }

    /**
     * <p>onInit</p>
     */
    public synchronized void onInit() {
        BeanUtils.assertAutowiring(this);

        Assert.state(m_backlogQ != null, "backlogQ must be set");

        try {
            m_trapdIpMgr.dataSourceSync();
        } catch (final SQLException e) {
            LOG.error("init: Failed to load known IP address list", e);
            throw new UndeclaredThrowableException(e);
        }

        try {
            InetAddress address = getInetAddress();
            LOG.info("Listening on {}:{}", address == null ? "[all interfaces]" : InetAddressUtils.str(address),
                    m_snmpTrapPort);
            SnmpUtils.registerForTraps(this, this, address, m_snmpTrapPort, m_snmpV3Users);
            m_registeredForTraps = true;

            LOG.debug("init: Creating the trap session");
        } catch (final IOException e) {
            if (e instanceof java.net.BindException) {
                Logging.withPrefix("OpenNMS.Manager", new Runnable() {
                    @Override
                    public void run() {
                        LOG.error(
                                "init: Failed to listen on SNMP trap port, perhaps something else is already listening?",
                                e);
                    }
                });
                LOG.error("init: Failed to listen on SNMP trap port, perhaps something else is already listening?",
                        e);
            } else {
                LOG.error("init: Failed to initialize SNMP trap socket", e);
            }
            throw new UndeclaredThrowableException(e);
        }

        try {
            m_eventReader.open();
        } catch (final Throwable e) {
            LOG.error("init: Failed to open event reader", e);
            throw new UndeclaredThrowableException(e);
        }
    }

    private InetAddress getInetAddress() {
        if (m_snmpTrapAddress.equals("*")) {
            return null;
        }
        return InetAddressUtils.addr(m_snmpTrapAddress);
    }

    /**
     * Create the SNMP trap session and create the communication channel
     * to communicate with eventd.
     *
     * @throws java.lang.reflect.UndeclaredThrowableException if an unexpected database, or IO exception occurs.
     * @see org.opennms.protocols.snmp.SnmpTrapSession
     * @see org.opennms.protocols.snmp.SnmpTrapHandler
     */

    public synchronized void onStart() {
        m_status = STARTING;

        LOG.debug("start: Initializing the trapd config factory");

        m_status = RUNNING;

        LOG.debug("start: Trapd ready to receive traps");
    }

    /**
     * Pauses Trapd
     */
    public void onPause() {
        if (m_status != RUNNING) {
            return;
        }

        m_status = PAUSE_PENDING;

        LOG.debug("pause: Calling pause on processor");

        m_status = PAUSED;

        LOG.debug("pause: Trapd paused");
    }

    /**
     * Resumes Trapd
     */
    public void onResume() {
        if (m_status != PAUSED) {
            return;
        }

        m_status = RESUME_PENDING;

        LOG.debug("resume: Calling resume on processor");

        m_status = RUNNING;

        LOG.debug("resume: Trapd resumed");
    }

    /**
     * Stops the currently running service. If the service is not running then
     * the command is silently discarded.
     */
    public synchronized void onStop() {
        m_status = STOP_PENDING;

        // shutdown and wait on the background processing thread to exit.
        LOG.debug("stop: closing communication paths.");

        try {
            if (m_registeredForTraps) {
                LOG.debug("stop: Closing SNMP trap session.");
                SnmpUtils.unregisterForTraps(this, getInetAddress(), m_snmpTrapPort);
                LOG.debug("stop: SNMP trap session closed.");
            } else {
                LOG.debug("stop: not attemping to closing SNMP trap session--it was never opened");
            }
        } catch (final IOException e) {
            LOG.warn("stop: exception occurred closing session", e);
        } catch (final IllegalStateException e) {
            LOG.debug("stop: The SNMP session was already closed", e);
        }

        LOG.debug("stop: Stopping queue processor.");

        m_backlogQ.shutdown();

        m_eventReader.close();

        m_status = STOPPED;

        LOG.debug("stop: Trapd stopped");
    }

    /**
     * Returns the current status of the service.
     *
     * @return The service's status.
     */
    public synchronized int getStatus() {
        return m_status;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void trapError(final int error, final String msg) {
        LOG.warn("Error Processing Received Trap: error = {} {}", error, (msg != null ? ", ref = " + msg : ""));
    }

    /**
     * <p>getEventReader</p>
     *
     * @return a {@link org.opennms.netmgt.trapd.BroadcastEventProcessor} object.
     */
    public BroadcastEventProcessor getEventReader() {
        return m_eventReader;
    }

    /**
     * <p>setEventReader</p>
     *
     * @param eventReader a {@link org.opennms.netmgt.trapd.BroadcastEventProcessor} object.
     */
    public void setEventReader(BroadcastEventProcessor eventReader) {
        m_eventReader = eventReader;
    }

    /**
     * <p>getBacklogQ</p>
     *
     * @return a {@link java.util.concurrent.ExecutorService} object.
     */
    public ExecutorService getBacklogQ() {
        return m_backlogQ;
    }

    /**
     * <p>setBacklogQ</p>
     *
     * @param backlogQ a {@link java.util.concurrent.ExecutorService} object.
     */
    public void setBacklogQ(ExecutorService backlogQ) {
        m_backlogQ = backlogQ;
    }

    public void setProcessorFactory(TrapQueueProcessorFactory m_processorFactory) {
        this.m_processorFactory = m_processorFactory;
    }

    public void setTrapdIpMgr(TrapdIpMgr m_trapdIpMgr) {
        this.m_trapdIpMgr = m_trapdIpMgr;
    }

    public void setSnmpTrapAddress(String m_snmpTrapAddress) {
        this.m_snmpTrapAddress = m_snmpTrapAddress;
    }

    public void setSnmpTrapPort(Integer m_snmpTrapPort) {
        this.m_snmpTrapPort = m_snmpTrapPort;
    }

    public void setSnmpV3Users(List<SnmpV3User> m_snmpV3Users) {
        this.m_snmpV3Users = m_snmpV3Users;
    }
}