/******************************************************************************* * 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.eventd.processor; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; import java.sql.Timestamp; import java.sql.Types; import java.util.ArrayList; import java.util.List; import org.opennms.core.utils.DBUtils; import org.opennms.core.utils.LogUtils; import org.opennms.netmgt.eventd.EventdConstants; import org.opennms.netmgt.eventd.db.AutoAction; import org.opennms.netmgt.eventd.db.OperatorAction; import org.opennms.netmgt.eventd.db.SnmpInfo; import org.opennms.netmgt.model.OnmsSeverity; import org.opennms.netmgt.model.events.Constants; import org.opennms.netmgt.model.events.Parameter; import org.opennms.netmgt.xml.event.Event; import org.opennms.netmgt.xml.event.Header; import org.opennms.netmgt.xml.event.Operaction; import org.springframework.beans.factory.InitializingBean; import org.springframework.dao.DataAccessException; import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.jdbc.core.simple.SimpleJdbcTemplate; /** * EventWriter loads the information in each 'Event' into the database. * * While loading multiple values of the same element into a single DB column, the * multiple values are delimited by MULTIPLE_VAL_DELIM. * * When an element and its attribute are loaded into a single DB column, the * value and the attribute are separated by a DB_ATTRIB_DELIM. * * When using delimiters to append values, if the values already have the * delimiter, the delimiter in the value is escaped as in URLs. * * Values for the ' <parms>' block are loaded with each parm name and parm value * delimited with the NAME_VAL_DELIM. * * @deprecated Replace with a Hibernate implementation. See bug NMS-3033. Actually * it doesn't have any details. :P * http://issues.opennms.org:8280/browse/NMS-3033 * * @see org.opennms.netmgt.model.events.Constants#MULTIPLE_VAL_DELIM * @see org.opennms.netmgt.model.events.Constants#DB_ATTRIB_DELIM * @see org.opennms.netmgt.model.events.Constants#NAME_VAL_DELIM * @see org.opennms.netmgt.model.events.Constants#MULTIPLE_VAL_DELIM * @see org.opennms.netmgt.model.events.Constants#DB_ATTRIB_DELIM * @see org.opennms.netmgt.model.events.Constants#NAME_VAL_DELIM * @see org.opennms.netmgt.model.events.Constants#MULTIPLE_VAL_DELIM * @see org.opennms.netmgt.model.events.Constants#DB_ATTRIB_DELIM * @see org.opennms.netmgt.model.events.Constants#NAME_VAL_DELIM * @author <A HREF="mailto:sowmya@opennms.org">Sowmya Nataraj </A> * @author <A HREF="http://www.opennms.org">OpenNMS.org </A> */ public final class JdbcEventWriter extends AbstractJdbcPersister implements EventProcessor, InitializingBean { /** * {@inheritDoc} * * The method that inserts the event into the database */ public void process(final Header eventHeader, final Event event) throws SQLException, DataAccessException { if (!checkEventSanityAndDoWeProcess(event, "JdbcEventWriter")) { return; } LogUtils.debugf(this, "JdbcEventWriter: processing %s nodeid: %d ipaddr: %s serviceid: %s time: %s", event.getUei(), event.getNodeid(), event.getInterface(), event.getService(), event.getTime()); final Connection connection = getDataSource().getConnection(); try { connection.setAutoCommit(false); try { insertEvent(eventHeader, event, connection); connection.commit(); } catch (final SQLException e) { LogUtils.warnf(this, e, "Error inserting event into the datastore."); try { connection.rollback(); } catch (final Throwable e2) { LogUtils.warnf(this, e2, "Rollback of transaction failed."); } throw e; } catch (final DataAccessException e) { LogUtils.warnf(this, e, "Error inserting event into the datastore."); try { connection.rollback(); } catch (final Throwable e2) { LogUtils.warnf(this, e2, "Rollback of transaction failed."); } throw e; } } finally { try { connection.close(); } catch (final SQLException e) { LogUtils.warnf(this, e, "SQLException while closing database connection."); } } LogUtils.debugf(this, "EventWriter finished for : %s", event.getUei()); } /** * Insert values into the EVENTS table * * @exception java.sql.SQLException * Thrown if there is an error adding the event to the * database. * @exception java.lang.NullPointerException * Thrown if a required resource cannot be found in the * properties file. */ private void insertEvent(final Header eventHeader, final Event event, final Connection connection) throws SQLException { // Execute the statement to get the next event id final int eventID = getNextId(); LogUtils.debugf(this, "DBID: %d", eventID); synchronized (event) { event.setDbid(eventID); } final DBUtils d = new DBUtils(getClass()); try { final PreparedStatement insStmt = connection.prepareStatement(EventdConstants.SQL_DB_INS_EVENT); d.watch(insStmt); // eventID insStmt.setInt(1, eventID); // eventUEI insStmt.setString(2, Constants.format(event.getUei(), EVENT_UEI_FIELD_SIZE)); // nodeID final Long nodeid = event.getNodeid(); set(insStmt, 3, event.hasNodeid() ? nodeid.intValue() : -1); // eventTime insStmt.setTimestamp(4, getEventTime(event)); // Resolve the event host to a hostname using the ipInterface table String hostname = getEventHost(event, connection); // eventHost set(insStmt, 5, Constants.format(hostname, EVENT_HOST_FIELD_SIZE)); // ipAddr set(insStmt, 6, Constants.format(event.getInterface(), EVENT_INTERFACE_FIELD_SIZE)); // eventDpName insStmt.setString(7, (eventHeader != null) ? Constants.format(eventHeader.getDpName(), EVENT_DPNAME_FIELD_SIZE) : "undefined"); // eventSnmpHost set(insStmt, 8, Constants.format(event.getSnmphost(), EVENT_SNMPHOST_FIELD_SIZE)); // service identifier - convert the service name to a service id set(insStmt, 9, getEventServiceId(event)); // eventSnmp if (event.getSnmp() != null) { insStmt.setString(10, SnmpInfo.format(event.getSnmp(), EVENT_SNMP_FIELD_SIZE)); } else { insStmt.setNull(10, Types.VARCHAR); } // eventParms // Replace any null bytes with a space, otherwise postgres will complain about encoding in UNICODE final String parametersString=Parameter.format(event); set(insStmt, 11, Constants.format(parametersString, 0)); // eventCreateTime final Timestamp eventCreateTime = new Timestamp(System.currentTimeMillis()); insStmt.setTimestamp(12, eventCreateTime); // eventDescr set(insStmt, 13, Constants.format(event.getDescr(), 0)); // eventLoggroup set(insStmt, 14, (event.getLoggroupCount() > 0) ? Constants.format(event.getLoggroup(), EVENT_LOGGRP_FIELD_SIZE) : null); // eventLogMsg // eventLog // eventDisplay if (event.getLogmsg() != null) { // set log message set(insStmt, 15, Constants.format(event.getLogmsg().getContent(), 0)); String logdest = event.getLogmsg().getDest(); if (logdest.equals("logndisplay")) { // if 'logndisplay' set both log and display column to yes set(insStmt, 16, MSG_YES); set(insStmt, 17, MSG_YES); } else if (logdest.equals("logonly")) { // if 'logonly' set log column to true set(insStmt, 16, MSG_YES); set(insStmt, 17, MSG_NO); } else if (logdest.equals("displayonly")) { // if 'displayonly' set display column to true set(insStmt, 16, MSG_NO); set(insStmt, 17, MSG_YES); } else if (logdest.equals("suppress")) { // if 'suppress' set both log and display to false set(insStmt, 16, MSG_NO); set(insStmt, 17, MSG_NO); } } else { insStmt.setNull(15, Types.VARCHAR); /* * If this is an event that had no match in the event conf * mark it as to be logged and displayed so that there * are no events that slip through the system * without the user knowing about them */ set(insStmt, 17, MSG_YES); } // eventSeverity set(insStmt, 18, OnmsSeverity.get(event.getSeverity()).getId()); // eventPathOutage set(insStmt, 19, (event.getPathoutage() != null) ? Constants.format(event.getPathoutage(), EVENT_PATHOUTAGE_FIELD_SIZE) : null); // eventCorrelation set(insStmt, 20, (event.getCorrelation() != null) ? org.opennms.netmgt.eventd.db.Correlation.format(event.getCorrelation(), EVENT_CORRELATION_FIELD_SIZE) : null); // eventSuppressedCount insStmt.setNull(21, Types.INTEGER); // eventOperInstruct set(insStmt, 22, Constants.format(event.getOperinstruct(), EVENT_OPERINSTRUCT_FIELD_SIZE)); // eventAutoAction set(insStmt, 23, (event.getAutoactionCount() > 0) ? AutoAction.format(event.getAutoaction(), EVENT_AUTOACTION_FIELD_SIZE) : null); // eventOperAction / eventOperActionMenuText if (event.getOperactionCount() > 0) { final List<Operaction> a = new ArrayList<Operaction>(); final List<String> b = new ArrayList<String>(); for (final Operaction eoa : event.getOperactionCollection()) { a.add(eoa); b.add(eoa.getMenutext()); } set(insStmt, 24, OperatorAction.format(a, EVENT_OPERACTION_FIELD_SIZE)); set(insStmt, 25, Constants.format(b, EVENT_OPERACTION_MENU_FIELD_SIZE)); } else { insStmt.setNull(24, Types.VARCHAR); insStmt.setNull(25, Types.VARCHAR); } // eventNotification, this column no longer needed insStmt.setNull(26, Types.VARCHAR); // eventTroubleTicket / eventTroubleTicket state if (event.getTticket() != null) { set(insStmt, 27, Constants.format(event.getTticket().getContent(), EVENT_TTICKET_FIELD_SIZE)); set(insStmt, 28, event.getTticket().getState().equals("on") ? 1 : 0); } else { insStmt.setNull(27, Types.VARCHAR); insStmt.setNull(28, Types.INTEGER); } // eventForward set(insStmt, 29, (event.getForwardCount() > 0) ? org.opennms.netmgt.eventd.db.Forward.format(event.getForward(), EVENT_FORWARD_FIELD_SIZE) : null); // event mouseOverText set(insStmt, 30, Constants.format(event.getMouseovertext(), EVENT_MOUSEOVERTEXT_FIELD_SIZE)); // eventAckUser if (event.getAutoacknowledge() != null && event.getAutoacknowledge().getState().equals("on")) { set(insStmt, 31, Constants.format(event.getAutoacknowledge().getContent(), EVENT_ACKUSER_FIELD_SIZE)); // eventAckTime - if autoacknowledge is present, // set time to event create time set(insStmt, 32, eventCreateTime); } else { insStmt.setNull(31, Types.INTEGER); insStmt.setNull(32, Types.TIMESTAMP); } // eventSource set(insStmt, 33, Constants.format(event.getSource(), EVENT_SOURCE_FIELD_SIZE)); // ifindex if (event.hasIfIndex()) { set(insStmt, 34, event.getIfIndex()); } else { insStmt.setNull(34, Types.INTEGER); } // execute insStmt.executeUpdate(); } finally { d.cleanUp(); } LogUtils.debugf(this, "SUCCESSFULLY added %s related data into the EVENTS table.", event.getUei()); } /** * This method is used to convert the event host into a hostname id by * performing a lookup in the database. If the conversion is successful then * the corresponding hosname will be returned to the caller. * @param nodeId TODO * @param hostip * The event host * * @return The hostname * * @exception java.sql.SQLException * Thrown if there is an error accessing the stored data or * the SQL text is malformed. * * @see EventdConstants#SQL_DB_HOSTIP_TO_HOSTNAME * */ // FIXME: This uses JdbcTemplate and not the passed in connection // FIXME: This uses JdbcTemplate and not the passed in connection String getHostName(final int nodeId, final String hostip, final Connection connection) throws SQLException { try { final String hostname = new SimpleJdbcTemplate(getDataSource()).queryForObject(EventdConstants.SQL_DB_HOSTIP_TO_HOSTNAME, String.class, new Object[] { nodeId, hostip }); return (hostname != null) ? hostname : hostip; } catch (final EmptyResultDataAccessException e) { return hostip; } } /** * @param event * @param log * @return */ private int getEventServiceId(final Event event) { if (event.getService() == null) { return -1; } try { return getServiceID(event.getService()); } catch (final Throwable t) { LogUtils.warnf(this, t, "Error converting service name \"%s\" to an integer identifier, storing -1.", event.getService()); return -1; } } /** * <p>getEventHost</p> * * @param event a {@link org.opennms.netmgt.xml.event.Event} object. * @param connection a {@link java.sql.Connection} object. * @return a {@link java.lang.String} object. */ protected String getEventHost(final Event event, final Connection connection) { if (event.getHost() == null) { return null; } // If the event doesn't have a node ID, we can't lookup the IP address and be sure we have the right one since we don't know what node it is on if (!event.hasNodeid()) { return event.getHost(); } try { return getHostName(event.getNodeid().intValue(), event.getHost(), connection); } catch (final Throwable t) { LogUtils.warnf(this, t, "Error converting host IP \"%s\" to a hostname, storing the IP.", event.getHost()); return event.getHost(); } } }