/******************************************************************************* * 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.scriptd.ins.events; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintStream; import java.io.StringWriter; import java.net.InetAddress; import java.net.Socket; import java.util.ArrayList; import java.util.Date; import java.util.List; import org.apache.commons.io.IOUtils; import org.hibernate.ObjectNotFoundException; import org.hibernate.criterion.Restrictions; import org.opennms.core.utils.BeanUtils; import org.opennms.core.utils.LogUtils; import org.opennms.core.xml.JaxbUtils; import org.opennms.netmgt.EventConstants; import org.opennms.netmgt.dao.EventDao; import org.opennms.netmgt.model.OnmsAlarm; import org.opennms.netmgt.model.OnmsCriteria; import org.opennms.netmgt.model.OnmsEvent; import org.opennms.netmgt.model.OnmsSeverity; import org.opennms.netmgt.model.events.Parameter; import org.opennms.netmgt.xml.event.AlarmData; import org.opennms.netmgt.xml.event.Event; import org.opennms.netmgt.xml.event.Logmsg; import org.opennms.netmgt.xml.event.Parm; import org.springframework.beans.factory.access.BeanFactoryReference; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.TransactionCallback; import org.springframework.transaction.support.TransactionTemplate; class InsSession extends InsAbstractSession { private Socket server; private String line, input; // private CurrentAlarmsSender sendCurrentAlarmsThread=null; private PrintStream streamToClient; // Client requests private final static String START_AUTHENTICATION_REQUEST = "AUTH"; private final static String LIST_CURRENT_ALARM_REQUEST = "LIST_CURRENT_ALARM_REQUEST"; private final static String STOP_ALARM_REQUEST = "STOP_ALARM"; // Server answers private final static String AUTH_REQUIRED_ACK = "AUTH_REQUIRED"; private final static String AUTH_NOT_REQUIRED_ACK = "AUTH_NOT_REQUIRED"; private final static String AUTHENTICATION_SUCCESS = "AUTH-SUCCESS"; private final static String RESET_SIGNAL = "RESET"; private final static String ACTIVE_ALARM_BEGIN = "ACTIVE_ALARM_BEGIN"; private final static String ACTIVE_ALARM_END = "ACTIVE_ALARM_END"; // session statuses private final int STARTING_SESSION_STATUS = 0; private final int AUTHENTICATING_STATUS = 1; private final int AUTHENTICATED_STATUS = 2; private final int DATAFLOW_STATUS = 3; private int status = STARTING_SESSION_STATUS; private List<Event> m_events = new ArrayList<Event>(); InsSession(Socket server) throws IOException { this.server = server; streamToClient = new PrintStream(server.getOutputStream()); } public void run() { input = ""; InputStreamReader isr = null; BufferedReader in = null; try { // Get input from the client isr = new InputStreamReader(server.getInputStream()); in = new BufferedReader(isr); readingFromClient: while ((line = in.readLine()) != null) { input = input + "\n" + line; LogUtils.debugf(this, "Client wrote: %s from %s", line, server.getInetAddress()); if (status == STARTING_SESSION_STATUS) { if (line.equalsIgnoreCase(START_AUTHENTICATION_REQUEST)) { if (getSharedASCIIString() != null) { LogUtils.debugf(this, "Starting authentication, sending %s to the client", AUTH_REQUIRED_ACK); streamToClient.println(AUTH_REQUIRED_ACK); status = AUTHENTICATING_STATUS; } else { LogUtils.debugf(this, "Starting authentication, sending %s to the client", AUTH_NOT_REQUIRED_ACK); streamToClient.println(AUTH_NOT_REQUIRED_ACK); status = AUTHENTICATED_STATUS; } continue readingFromClient; } else { // security reset (a malicious user may use DOS attack before authentication) LogUtils.warnf(this, "Wrong client request"); break readingFromClient; } } if (status == AUTHENTICATING_STATUS) { if (getSharedASCIIString() != null) { // authentication required (security check) if (line.equals(getSharedASCIIString())) { status = AUTHENTICATED_STATUS; LogUtils.debugf(this, "Authentication success!"); streamToClient.println(AUTHENTICATION_SUCCESS); continue readingFromClient; } else { streamToClient.println(RESET_SIGNAL); LogUtils.warnf(this, "Authentication failure! Resetting session."); break readingFromClient; } } } if (status == AUTHENTICATED_STATUS || status == DATAFLOW_STATUS) { if (line.equalsIgnoreCase(LIST_CURRENT_ALARM_REQUEST)) { LogUtils.debugf(this, "Fetching Events from Database"); getEventsByCriteria(); status = DATAFLOW_STATUS; synchronized (streamToClient) { streamToClient.println(ACTIVE_ALARM_BEGIN); final StringWriter sw = getOutput(); if (sw != null) { final String output = sw.toString(); LogUtils.infof(this, "String Writer: %s", output); streamToClient.print(output); } else { LogUtils.errorf(this, "String Writer is null"); } streamToClient.println(ACTIVE_ALARM_END); continue readingFromClient; } } else { if (line.equalsIgnoreCase(STOP_ALARM_REQUEST)) { LogUtils.debugf(this, "Closing session due client request."); break readingFromClient; } else { LogUtils.warnf(this, "Wrong client request"); continue readingFromClient; } } } } LogUtils.debugf(this, "Closing session. Overall message from %s is: %s", server.getInetAddress(), input); server.close(); } catch (final IOException ioe) { LogUtils.warnf(this, ioe, "Error while listening to socket."); } finally { IOUtils.closeQuietly(in); IOUtils.closeQuietly(isr); } } public PrintStream getStreamToClient() { if (status == DATAFLOW_STATUS) return streamToClient; else return null; } private StringWriter getOutput() { LogUtils.debugf(this, "Sending alarms to the client"); final StringWriter sw = new StringWriter(); final List<Event> events = getEvents(); if (events != null) { for (final Event xmlEvent : events) { LogUtils.infof(this, "Marshal Event with id: %s", xmlEvent.getDbid()); JaxbUtils.marshal(xmlEvent, sw); LogUtils.debugf(this, "Flushing Event with id: %s", xmlEvent.getDbid()); sw.flush(); } } return sw; } private Event getXMLEvent(final OnmsEvent ev) { final Integer id = ev.getId(); LogUtils.infof(this, "Working on XML Event for id: %s", id); LogUtils.debugf(this, "Setting Event id: %s", id); final Event e = new Event(); e.setDbid(id); //UEI final String uei = ev.getEventUei(); if (uei != null) { LogUtils.debugf(this, "Setting Event uei: %s", uei); e.setUei(uei); } else { LogUtils.warnf(this, "No Event uei found: skipping event...."); return null; } // Source final String source = ev.getEventSource(); if (source != null) { LogUtils.debugf(this, "Setting Event source: %s", source); e.setSource(source); } else { LogUtils.infof(this, "No Event source found."); } //nodeid final Integer nodeid = ev.getNode().getId(); if (ev.getNode() != null && nodeid != null) { LogUtils.debugf(this, "Setting Event nodeid: %s", nodeid); e.setNodeid(nodeid.longValue()); } else { LogUtils.infof(this, "No Event node found."); } // timestamp final Date time = ev.getEventTime(); if (time != null) { LogUtils.debugf(this, "Setting event date timestamp to (GMT): %s", time); e.setTime(EventConstants.formatToString(time)); } else { LogUtils.infof(this, "No Event time found."); } // host final String host = ev.getEventHost(); if (host != null) { LogUtils.debugf(this, "Setting Event Host: %s", host); e.setHost(host); } else { LogUtils.infof(this, "No Event host found."); } // interface final InetAddress ipAddr = ev.getIpAddr(); if (ipAddr != null) { LogUtils.debugf(this, "Setting Event Interface/ipaddress: %s", ipAddr); e.setInterfaceAddress(ipAddr); } else { LogUtils.infof(this, "No Event ip address found."); } // Service Name if (ev.getServiceType() != null) { final String serviceName = ev.getServiceType().getName(); LogUtils.debugf(this, "Setting Event Service Name: %s", serviceName); e.setService(serviceName); } else { LogUtils.infof(this, "No Event service name found."); } // Description final String descr = ev.getEventDescr(); if (descr != null ) { LogUtils.debugf(this, "Setting Event Description: %s", descr); e.setDescr(descr); } else { LogUtils.infof(this, "No Event ip address found."); } // Log message final String logmsg = ev.getEventLogMsg(); if (logmsg != null) { final Logmsg msg = new Logmsg(); LogUtils.debugf(this, "Setting Event Log Message: %s", logmsg); msg.setContent(logmsg); e.setLogmsg(msg); } else { LogUtils.infof(this, "No Event log Message found."); } // severity final Integer severity = ev.getEventSeverity(); if (severity != null) { LogUtils.debugf(this, "Setting Event Severity: %s", severity); e.setSeverity(OnmsSeverity.get(severity).getLabel()); } else { LogUtils.infof(this, "No Event severity found."); } final Integer ifIndex = ev.getIfIndex(); if (ifIndex != null && ifIndex > 0 ) { e.setIfIndex(ifIndex); e.setIfAlias(getIfAlias(nodeid,ifIndex)); } else { e.setIfIndex(-1); e.setIfAlias("-1"); } // operator Instruction final String operInstruct = ev.getEventOperInstruct(); if (operInstruct != null) { LogUtils.debugf(this, "Setting Event Operator Instruction: %s", operInstruct); e.setOperinstruct(operInstruct); } else { LogUtils.infof(this, "No Event operator Instruction found."); } // parms final String eventParms = ev.getEventParms(); if (eventParms != null) { LogUtils.debugf(this, "Setting Event Parms: %s", eventParms); final List<Parm> parms = Parameter.decode(eventParms); if (parms != null) e.setParmCollection(parms); } else { LogUtils.infof(this, "No Event parms found."); } final AlarmData ad = new AlarmData(); final OnmsAlarm onmsAlarm = ev.getAlarm(); try { if (onmsAlarm != null) { ad.setReductionKey(onmsAlarm.getReductionKey()); ad.setAlarmType(onmsAlarm.getAlarmType()); ad.setClearKey(onmsAlarm.getClearKey()); e.setAlarmData(ad); } } catch (final ObjectNotFoundException e1) { LogUtils.warnf(this, e1, "Correlated alarm data not found."); } LogUtils.infof(this, "Returning event with id: %s", id); return e; } private void getEventsByCriteria() { LogUtils.debugf(this, "clearing events"); clearEvents(); final BeanFactoryReference bf = BeanUtils.getBeanFactory("daoContext"); final EventDao eventDao = BeanUtils.getBean(bf,"eventDao", EventDao.class); final TransactionTemplate transTemplate = BeanUtils.getBean(bf, "transactionTemplate",TransactionTemplate.class); try { transTemplate.execute(new TransactionCallback<Object>() { public Object doInTransaction(final TransactionStatus status) { LogUtils.debugf(this, "Entering transaction call back: selection with criteria: %s", criteriaRestriction); final OnmsCriteria criteria = new OnmsCriteria(OnmsEvent.class); criteria.add(Restrictions.sqlRestriction(criteriaRestriction)); final List<OnmsEvent> events = eventDao.findMatching(criteria); LogUtils.infof(this, "Found %d event(s) with criteria: %s", events.size(), criteriaRestriction); for (final OnmsEvent onmsEvent : events) { final Event xmlEvent = getXMLEvent(onmsEvent); if (xmlEvent != null) addEvent(xmlEvent); } return new Object(); } }); } catch (final RuntimeException e) { LogUtils.errorf(this, e, "Error while getting events."); } } private void addEvent(final Event event) { m_events.add(event); } private void clearEvents() { m_events.clear(); } private List<Event> getEvents() { return m_events; } final static char MULTIPLE_VAL_DELIM = ';'; final static char NAME_VAL_DELIM = '='; final static char DB_ATTRIB_DELIM = ','; }