/*******************************************************************************
* This file is part of OpenNMS(R).
*
* Copyright (C) 2009-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.ackd;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import junit.framework.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.opennms.core.test.MockLogAppender;
import org.opennms.core.test.OpenNMSJUnit4ClassRunner;
import org.opennms.core.utils.BeanUtils;
import org.opennms.netmgt.EventConstants;
import org.opennms.netmgt.ackd.AckReader.AckReaderState;
import org.opennms.netmgt.config.ackd.Reader;
import org.opennms.netmgt.dao.AcknowledgmentDao;
import org.opennms.netmgt.dao.AlarmDao;
import org.opennms.netmgt.dao.DatabasePopulator;
import org.opennms.netmgt.dao.EventDao;
import org.opennms.netmgt.dao.NodeDao;
import org.opennms.netmgt.dao.NotificationDao;
import org.opennms.netmgt.dao.UserNotificationDao;
import org.opennms.netmgt.dao.db.JUnitConfigurationEnvironment;
import org.opennms.netmgt.dao.db.JUnitTemporaryDatabase;
import org.opennms.netmgt.model.AckType;
import org.opennms.netmgt.model.OnmsAcknowledgment;
import org.opennms.netmgt.model.OnmsAlarm;
import org.opennms.netmgt.model.OnmsEvent;
import org.opennms.netmgt.model.OnmsNode;
import org.opennms.netmgt.model.OnmsNotification;
import org.opennms.netmgt.model.OnmsSeverity;
import org.opennms.netmgt.model.OnmsUserNotification;
import org.opennms.netmgt.model.acknowledgments.AckService;
import org.opennms.netmgt.model.events.EventBuilder;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.transaction.BeforeTransaction;
import org.springframework.transaction.annotation.Transactional;
/**
* Acknowledgment Daemon tests
*
* @author <a href="mailto:david@opennms.org">David Hustace</a>
*/
@RunWith(OpenNMSJUnit4ClassRunner.class)
@ContextConfiguration(locations={
"classpath:/META-INF/opennms/applicationContext-dao.xml",
"classpath*:/META-INF/opennms/component-dao.xml",
"classpath:/META-INF/opennms/applicationContext-daemon.xml",
"classpath*:/META-INF/opennms/component-service.xml",
"classpath:/META-INF/opennms/mockEventIpcManager.xml",
"classpath:/META-INF/opennms/applicationContext-setupIpLike-enabled.xml",
"classpath:/META-INF/opennms/applicationContext-ackd.xml",
"classpath:/META-INF/opennms/applicationContext-databasePopulator.xml",
"classpath:/META-INF/opennms/applicationContext-minimal-conf.xml"
})
@JUnitConfigurationEnvironment
@JUnitTemporaryDatabase(dirtiesContext=false)
@Transactional
public class AckdTest implements InitializingBean {
@Autowired
private AckService m_ackService;
@Autowired
private AlarmDao m_alarmDao;
@Autowired
private EventDao m_eventDao;
@Autowired
private Ackd m_daemon;
@Autowired
private AcknowledgmentDao m_ackDao;
@Autowired
private NodeDao m_nodeDao;
@Autowired
private DatabasePopulator m_populator;
@Autowired
private NotificationDao m_notificationDao;
@Autowired
private UserNotificationDao m_userNotificationDao;
private static boolean m_populated = false;
@BeforeTransaction
public void populateDatabase() {
try {
if (!m_populated) {
m_populator.populateDatabase();
}
} catch (Throwable e) {
e.printStackTrace(System.err);
} finally {
m_populated = true;
}
}
@Before
public void setUp() throws Exception {
Properties props = new Properties();
props.setProperty("log4j.logger.org.hibernate", "INFO");
props.setProperty("log4j.logger.org.springframework", "INFO");
props.setProperty("log4j.logger.org.hibernate.SQL", "DEBUG");
MockLogAppender.setupLogging(props);
}
@Override
public void afterPropertiesSet() throws Exception {
BeanUtils.assertAutowiring(this);
Assert.assertSame("dao from populator should refer to same dao from local properties", m_populator.getAcknowledgmentDao(), m_ackDao);
}
@Test
public void testRestartReaders() throws Exception {
AckReader reader = m_daemon.getAckReaders().get(0);
Reader readerConfig = m_daemon.getConfigDao().getReader("JavaMailReader");
readerConfig.setEnabled(true);
Assert.assertTrue("Unexpected reader state: "+reader.getState(), AckReaderState.STOPPED.equals(reader.getState()));
m_daemon.restartReaders(false);
Thread.sleep(30);
Assert.assertTrue("Unexpected reader state: "+reader.getState(), AckReaderState.STARTED.equals(reader.getState()));
m_daemon.pauseReaders();
Thread.sleep(30);
Assert.assertTrue("Unexpected reader state: "+reader.getState(), AckReaderState.PAUSED.equals(reader.getState()));
m_daemon.resumeReaders();
Thread.sleep(30);
Assert.assertTrue("Unexpected reader state: "+reader.getState(), AckReaderState.RESUMED.equals(reader.getState()));
readerConfig.setEnabled(false);
m_daemon.restartReaders(true);
Thread.sleep(300);
Assert.assertTrue("Unexpected reader state: "+reader.getState(), AckReaderState.STOPPED.equals(reader.getState()));
m_daemon.resumeReaders();
Thread.sleep(30);
Assert.assertTrue("Unexpected reader state: "+reader.getState(), AckReaderState.STOPPED.equals(reader.getState()));
readerConfig.setEnabled(true);
m_daemon.startReaders();
Thread.sleep(300);
Assert.assertTrue("Unexpected reader state: "+reader.getState(), AckReaderState.STARTED.equals(reader.getState()));
m_daemon.destroy();
}
/**
* Make sure the DB is not empty
*/
@Test
public void testDbState() {
Assert.assertFalse(m_nodeDao.findAll().isEmpty());
}
/**
* This tests the acknowledgment of an alarm and any related notifications.
*/
@Test
public void testAcknowledgeAlarm() {
VerificationObject vo = createAckStructure();
Assert.assertTrue(vo.m_nodeId > 0);
Assert.assertTrue(vo.m_alarmId > 0);
Assert.assertTrue(vo.m_eventID > 0);
Assert.assertTrue(vo.m_userNotifId > 0);
OnmsAlarm alarm = m_alarmDao.get(vo.m_alarmId);
OnmsAcknowledgment ack = new OnmsAcknowledgment(m_alarmDao.get(vo.m_alarmId));
m_ackDao.save(ack);
m_ackDao.flush();
m_ackService.processAck(ack);
alarm = m_alarmDao.get(ack.getRefId());
Assert.assertNotNull(alarm.getAlarmAckUser());
Assert.assertEquals("admin", alarm.getAlarmAckUser());
OnmsNotification notif = m_notificationDao.get(vo.m_notifId);
Assert.assertNotNull(notif);
Assert.assertEquals("admin", notif.getAnsweredBy());
Assert.assertTrue(alarm.getAlarmAckTime().before(notif.getRespondTime()));
}
/**
* This tests acknowledging a notification and a related alarm. If events are being deduplicated
* they should all have the same alarm ID.
* @throws InterruptedException
*/
@Test
public void testAcknowledgeNotification() throws InterruptedException {
VerificationObject vo = createAckStructure();
Assert.assertTrue(vo.m_nodeId > 0);
Assert.assertTrue(vo.m_alarmId > 0);
Assert.assertTrue(vo.m_eventID > 0);
Assert.assertTrue(vo.m_userNotifId > 0);
OnmsAcknowledgment ack = new OnmsAcknowledgment(m_notificationDao.get(vo.m_notifId));
m_ackDao.save(ack);
m_ackDao.flush();
Thread.sleep(1);
m_ackService.processAck(ack);
OnmsNotification notif = m_notificationDao.get(ack.getRefId());
Assert.assertNotNull(notif.getAnsweredBy());
Assert.assertEquals("admin", notif.getAnsweredBy());
OnmsAlarm alarm = m_alarmDao.get(vo.m_alarmId);
Assert.assertNotNull(alarm);
Assert.assertEquals("admin", alarm.getAlarmAckUser());
long ackTime = ack.getAckTime().getTime();
long respondTime = notif.getRespondTime().getTime();
//the DAOs now set the acknowledgment time for each Acknowledgable and should
//be later (by a few millis in this test) than the time the acknowledgment was created
//this will give us an idea about the processing time of an acknowledgment
Assert.assertTrue(ackTime < respondTime);
}
@Test
public void testHandelEvent() throws InterruptedException {
VerificationObject vo = createAckStructure();
EventBuilder bldr = new EventBuilder(EventConstants.ACKNOWLEDGE_EVENT_UEI, "AckdTest");
bldr.addParam("ackType", String.valueOf(AckType.ALARM));
bldr.addParam("refId", vo.m_alarmId);
final String user = "ackd-test-user";
bldr.addParam("user", user);
m_daemon.handleAckEvent(bldr.getEvent());
OnmsNotification notif = m_notificationDao.get(vo.m_notifId);
Assert.assertEquals(notif.getAckUser(), user);
// Assert.assertEquals(notif.getAckTime(), bldr.getEvent().getTime());
OnmsAlarm alarm = m_alarmDao.get(vo.m_alarmId);
Assert.assertEquals(alarm.getAckUser(), user);
// Assert.assertEquals(alarm.getAckTime(), bldr.getEvent().getTime());
}
class VerificationObject {
int m_eventID;
int m_alarmId;
int m_nodeId;
int m_notifId;
int m_userNotifId;
}
private VerificationObject createAckStructure() {
final Date time = new Date();
VerificationObject vo = new VerificationObject();
List<OnmsNode> nodes = m_nodeDao.findAll();
Assert.assertTrue("List of nodes should not be empty", nodes.size() > 0);
OnmsNode node = m_nodeDao.get(nodes.get(0).getId());
vo.m_nodeId = node.getId();
OnmsEvent event = new OnmsEvent();
event.setDistPoller(node.getDistPoller());
event.setNode(node);
event.setEventCreateTime(time);
event.setEventDescr("Test node down event.");
event.setEventSeverity(6);
event.setEventSource("AckdTest");
event.setEventTime(time);
event.setEventUei(EventConstants.NODE_DOWN_EVENT_UEI);
event.setIpAddr(node.getPrimaryInterface().getIpAddress());
event.setEventLog("Y");
event.setEventDisplay("Y");
event.setEventLogMsg("Testing node down event from AckdTest.");
m_eventDao.save(event);
m_eventDao.flush();
vo.m_eventID = event.getId();
OnmsAlarm alarm = new OnmsAlarm();
alarm.setAlarmType(1);
alarm.setClearKey(EventConstants.NODE_UP_EVENT_UEI + ":localhost:1");
alarm.setCounter(1);
alarm.setDescription(event.getEventDescr());
alarm.setDistPoller(event.getDistPoller());
alarm.setFirstEventTime(event.getEventTime());
alarm.setIpAddr(event.getIpAddr());
alarm.setLastEvent(event);
alarm.setLastEventTime(event.getEventTime());
alarm.setLogMsg("Some Log Message");
alarm.setNode(event.getNode());
alarm.setReductionKey("xyz");
alarm.setServiceType(event.getServiceType());
alarm.setSeverity(OnmsSeverity.get(event.getEventSeverity()));
alarm.setUei(event.getEventUei());
m_alarmDao.save(alarm);
m_alarmDao.flush();
vo.m_alarmId = alarm.getId();
event.setAlarm(alarm);
OnmsNotification notif = new OnmsNotification();
notif.setEvent(event);
notif.setEventUei(event.getEventUei());
notif.setIpAddress(event.getIpAddr());
notif.setNode(event.getNode());
notif.setNotifConfigName("abc");
notif.setNumericMsg(event.getEventLogMsg());
notif.setPageTime(event.getEventTime());
notif.setServiceType(event.getServiceType());
notif.setSubject("notifyid: 1, node down");
notif.setTextMsg(event.getEventLogMsg());
m_notificationDao.save(notif);
vo.m_notifId = notif.getNotifyId();
OnmsUserNotification userNotif = new OnmsUserNotification();
userNotif.setAutoNotify("Y");
userNotif.setContactInfo("me@yourock.com");
userNotif.setMedia("page");
userNotif.setNotification(notif);
userNotif.setNotifyTime(event.getEventTime());
userNotif.setUserId("me");
Set<OnmsUserNotification> usersnotifieds = new HashSet<OnmsUserNotification>();
usersnotifieds.add(userNotif);
m_userNotificationDao.save(userNotif);
vo.m_userNotifId = userNotif.getId();
notif.setUsersNotified(usersnotifieds);
m_notificationDao.update(notif);
m_eventDao.update(event);
m_eventDao.flush();
return vo;
}
}