/*******************************************************************************
* This file is part of OpenNMS(R).
*
* Copyright (C) 2006-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.passive;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.exolab.castor.xml.MarshalException;
import org.exolab.castor.xml.ValidationException;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.opennms.core.test.MockLogAppender;
import org.opennms.core.utils.InetAddressUtils;
import org.opennms.netmgt.EventConstants;
import org.opennms.netmgt.config.DataSourceFactory;
import org.opennms.netmgt.mock.EventAnticipator;
import org.opennms.netmgt.mock.MockDatabase;
import org.opennms.netmgt.mock.MockEventIpcManager;
import org.opennms.netmgt.mock.MockEventUtil;
import org.opennms.netmgt.mock.MockMonitoredService;
import org.opennms.netmgt.mock.MockNetwork;
import org.opennms.netmgt.mock.MockService;
import org.opennms.netmgt.mock.OutageAnticipator;
import org.opennms.netmgt.model.PollStatus;
import org.opennms.netmgt.poller.ServiceMonitor;
import org.opennms.netmgt.poller.monitors.PassiveServiceMonitor;
import org.opennms.netmgt.xml.event.Event;
import org.opennms.netmgt.xml.event.Logmsg;
import org.opennms.netmgt.xml.event.Parm;
import org.opennms.netmgt.xml.event.Value;
public class PassiveStatusKeeperTest {
/* TODO for PassiveSTatusKeeper
add reason mapper for status reason
be able to create an event with translated values
- determine new event values based on config
- assign computed values to new event
- copy over (or not) untranslated attributes
make sure we can translate uei if desired
modify passive status config to handle specific event with specific parms
*/
private PassiveStatusKeeper m_psk;
private MockEventIpcManager m_eventMgr;
private MockDatabase m_db;
private MockNetwork m_network;
private EventAnticipator m_anticipator;
private OutageAnticipator m_outageAnticipator;
@Before
public void setUp() throws Exception {
// MockUtil.println("------------ Begin Test "+getName()+" --------------------------");
MockLogAppender.setupLogging();
createMockNetwork();
createMockDb();
createAnticipators();
m_eventMgr = new MockEventIpcManager();
m_eventMgr.setEventWriter(m_db);
m_eventMgr.setEventAnticipator(m_anticipator);
m_eventMgr.addEventListener(m_outageAnticipator);
m_eventMgr.setSynchronous(true);
m_psk = new PassiveStatusKeeper();
m_psk.setEventManager(m_eventMgr);
m_psk.setDataSource(m_db);
PassiveStatusKeeper.setInstance(m_psk);
m_psk.init();
m_psk.start();
}
@After
public void tearDown() throws Exception {
m_eventMgr.finishProcessingEvents();
m_psk.stop();
sleep(200);
MockLogAppender.assertNoWarningsOrGreater();
m_db.drop();
// MockUtil.println("------------ End Test "+getName()+" --------------------------");
}
private void createAnticipators() {
m_anticipator = new EventAnticipator();
m_outageAnticipator = new OutageAnticipator(m_db);
}
private void createMockDb() throws Exception {
m_db = new MockDatabase();
m_db.populate(m_network);
DataSourceFactory.setInstance(m_db);
}
private void createMockNetwork() {
m_network = new MockNetwork();
m_network.setCriticalService("ICMP");
m_network.addNode(1, "Router");
m_network.addInterface("192.168.1.1");
m_network.addService("ICMP");
m_network.addService("SMTP");
m_network.addInterface("192.168.1.2");
m_network.addService("ICMP");
m_network.addService("SMTP");
m_network.addNode(2, "Server");
m_network.addInterface("192.168.1.3");
m_network.addService("ICMP");
m_network.addService("HTTP");
m_network.addNode(3, "Firewall");
m_network.addInterface("192.168.1.4");
m_network.addService("SMTP");
m_network.addService("HTTP");
m_network.addInterface("192.168.1.5");
m_network.addService("SMTP");
m_network.addService("HTTP");
m_network.addNode(100, "localhost");
m_network.addInterface("127.0.0.1");
m_network.addService("PSV");
m_network.addService("PSV2");
}
private void sleep(long millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
}
}
/**
* This is a test for the passive status keeper where all the required parms are included
* in the event.
*/
@Test
public void testEventWithPassiveStatusParms() {
Event e = createPassiveStatusEvent("Router", "192.168.1.1", "ICMP", "Down");
assertTrue(m_psk.isPassiveStatusEvent(e));
}
/**
* This is a test for the method that verifies valid passive status events
* for the passive status keeper.
* @throws ValidationException
* @throws MarshalException
*
*/
@Test
public void testIsPassiveStatusEvent() throws MarshalException, ValidationException {
Event e = createPassiveStatusEvent("Router", "192.168.1.1", "ICMP", "Down");
assertTrue(m_psk.isPassiveStatusEvent(e));
//test for missing required parms
e = createPassiveStatusEvent("Router", "192.168.1.1", null, "Down");
assertFalse(m_psk.isPassiveStatusEvent(e));
//this will test the event simply doesn't match a registered uei.
e.setUei("bogusUei");
assertFalse(m_psk.isPassiveStatusEvent(e));
}
@Test
public void testSetStatus() {
testSetStatus("localhost", "127.0.0.1", "PSV", PollStatus.up());
}
private void testSetStatus(String nodeLabel, String ipAddr, String svcName, PollStatus pollStatus) {
PassiveStatusKeeper.getInstance().setStatus(nodeLabel, ipAddr, svcName, pollStatus);
assertEquals(pollStatus, PassiveStatusKeeper.getInstance().getStatus(nodeLabel, ipAddr, svcName));
}
@Test
public void testRestart() {
testSetStatus("localhost", "127.0.0.1", "PSV", PollStatus.up());
testSetStatus("localhost", "127.0.0.1", "PSV2", PollStatus.down());
MockService svc = m_network.getService(100, "127.0.0.1", "PSV2");
Event downEvent = svc.createDownEvent();
m_db.writeEvent(downEvent);
m_db.createOutage(svc, downEvent);
m_psk.stop();
m_psk.setEventManager(m_eventMgr);
m_psk.setDataSource(m_db);
m_psk.init();
m_psk.start();
assertEquals(PollStatus.up(), PassiveStatusKeeper.getInstance().getStatus("localhost", "127.0.0.1", "PSV"));
assertEquals(PollStatus.down(), PassiveStatusKeeper.getInstance().getStatus("localhost", "127.0.0.1", "PSV2"));
}
@Test
public void testDownPassiveStatus() throws InterruptedException, UnknownHostException {
Event e = createPassiveStatusEvent("Router", "192.168.1.1", "ICMP", "Down");
m_eventMgr.sendNow(e);
PollStatus ps = m_psk.getStatus("Router", "192.168.1.1", "ICMP");
assertTrue(ps.isDown());
MockMonitoredService svc = new MockMonitoredService(1, "Router", InetAddressUtils.addr("192.168.1.1"), "ICMP" );
ServiceMonitor m = new PassiveServiceMonitor();
m.initialize((Map<String,Object>)null);
m.initialize(svc);
PollStatus ps2 = m.poll(svc, null);
m.release(svc);
m.release();
assertEquals(ps, ps2);
}
private Event createPassiveStatusEvent(String nodeLabel, String ipAddr, String serviceName, String status) {
final List<Parm> parms = new ArrayList<Parm>();
if(nodeLabel != null) parms.add(buildParm(EventConstants.PARM_PASSIVE_NODE_LABEL, nodeLabel));
if(ipAddr != null) parms.add(buildParm(EventConstants.PARM_PASSIVE_IPADDR, ipAddr));
if(serviceName != null) parms.add(buildParm(EventConstants.PARM_PASSIVE_SERVICE_NAME, serviceName));
if(status != null) parms.add(buildParm(EventConstants.PARM_PASSIVE_SERVICE_STATUS, status));
return createEventWithParms("uei.opennms.org/services/passiveServiceStatus", parms);
}
private Event createEventWithParms(String uei, List<Parm> parms) {
Event e = MockEventUtil.createEventBuilder("Test", uei).getEvent();
e.setHost("localhost");
e.setParmCollection(parms);
Logmsg logmsg = new Logmsg();
logmsg.setContent("Testing Passive Status Keeper with down status");
e.setLogmsg(logmsg);
return e;
}
private Parm buildParm(String parmName, String parmValue) {
Value v = new Value();
v.setContent(parmValue);
Parm p = new Parm();
p.setParmName(parmName);
p.setValue(v);
return p;
}
@SuppressWarnings("unused")
private String getTranslationTestConfig() {
return "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<passive-status-configuration \n" +
"xmlns=\"http://xmlns.opennms.org/xsd/passive-status-configuration\" \n" +
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" >\n" +
" <translation>\n" +
" <event-translation-spec uei=\"uei.opennms.org/services/translationEvent\">\n" +
" <mappings>\n" +
" <mapping>\n" +
" <assignment type=\"field\" name=\"nodeid\">\n" +
" <value type=\"sql\" result=\"select node.nodeid from node, ipInterface where node.nodeLabel=? and ipinterface.ipaddr=? and node.nodeId=ipinterface.nodeid and ipInterface.isManaged != 'D' and node.nodeType != 'D'\" >\n" +
" <value type=\"parameter\" name=\"passiveNodeLabel\" matches=\"Router\" result=\"Firewall\" />\n" +
" <value type=\"constant\" result=\"192.168.1.4\" />\n" +
" </value>\n" +
" </assignment>\n" +
" <assignment type=\"parameter\" name=\"nodeLabel\">\n" +
" <value type=\"field\" name=\"host\" result=\"Switch\" />\n" +
" </assignment>\n" +
" <assignment type=\"field\" name=\"interface\">\n" +
" <value type=\"parameter\" name=\"passiveIpAddr\" matches=\".*(192\\.168\\.1\\.1).*\" result=\"192.168.1.1\" />\n" +
" </assignment>\n" +
" <assignment type=\"field\" name=\"host\">\n" +
" <value type=\"field\" name=\"host\" result=\"www.opennms.org\" />\n" +
" </assignment>\n" +
" <assignment type=\"field\" name=\"descr\">\n" +
" <value type=\"constant\" result=\"a generated event\" />\n" +
" </assignment>\n" +
" <assignment type=\"field\" name=\"service\">\n" +
" <value type=\"parameter\" name=\"passiveServiceName\" result=\"PSV\" />\n" +
" </assignment>\n" +
" <assignment type=\"parameter\" name=\"passiveStatus\">\n" +
" <value type=\"parameter\" name=\"passiveStatus\" matches=\".*(Up|Down).*\" result=\"${1}\" />\n" +
" </assignment>\n" +
" </mapping>\n" +
" </mappings>\n" +
" </event-translation-spec>\n" +
" </translation>\n" +
"</passive-status-configuration>\n" +
"";
}
@SuppressWarnings("unused")
private String getStandardConfig() {
return "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<passive-status-configuration \n" +
"xmlns=\"http://xmlns.opennms.org/xsd/passive-status-configuration\" \n" +
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" >\n" +
" <translation>\n" +
" <event-translation-spec uei=\"uei.opennms.org/services/translationEvent\">\n" +
" <mappings>\n" +
" <mapping>\n" +
" <assignment type=\"field\" name=\"nodeid\">\n" +
" <value type=\"sql\" result=\"select node.nodeid from node, ipInterface where node.nodeLabel=? and ipinterface.ipaddr=? and node.nodeId=ipinterface.nodeid and ipInterface.isManaged != 'D' and node.nodeType != 'D'\" >\n" +
" <value type=\"parameter\" name=\"passiveNodeLabel\" matches=\"Router\" result=\"Firewall\" />\n" +
" <value type=\"constant\" result=\"192.168.1.4\" />\n" +
" </value>\n" +
" </assignment>\n" +
" <assignment type=\"parameter\" name=\"nodeLabel\">\n" +
" <value type=\"field\" name=\"host\" result=\"Switch\" />\n" +
" </assignment>\n" +
" <assignment type=\"field\" name=\"interface\">\n" +
" <value type=\"parameter\" name=\"passiveIpAddr\" matches=\".*(192\\.168\\.1\\.1).*\" result=\"192.168.1.1\" />\n" +
" </assignment>\n" +
" <assignment type=\"field\" name=\"host\">\n" +
" <value type=\"field\" name=\"host\" result=\"www.opennms.org\" />\n" +
" </assignment>\n" +
" <assignment type=\"field\" name=\"descr\">\n" +
" <value type=\"constant\" result=\"a generated event\" />\n" +
" </assignment>\n" +
" <assignment type=\"field\" name=\"service\">\n" +
" <value type=\"parameter\" name=\"passiveServiceName\" result=\"PSV\" />\n" +
" </assignment>\n" +
" <assignment type=\"parameter\" name=\"passiveStatus\">\n" +
" <value type=\"parameter\" name=\"passiveStatus\" matches=\".*(Up|Down).*\" result=\"${1}\" />\n" +
" </assignment>\n" +
" </mapping>\n" +
" </mappings>\n" +
" </event-translation-spec>\n" +
" </translation>\n" +
" <passive-events>\n" +
" <passive-event uei=\"uei.opennms.org/services/passiveServiceStatus\">\n" +
" <status-key>\n" +
" <node-label>\n" +
" <event-token is-parm=\"true\" name=\"passiveNodeLabel\" value=\"Router\"/>\n" +
" </node-label>\n" +
" <ipaddr>\n" +
" <event-token is-parm=\"true\" name=\"passiveIpAddr\" value=\"192.168.1.1\"/>\n" +
" </ipaddr>\n" +
" <service-name>\n" +
" <event-token is-parm=\"true\" name=\"passiveServiceName\" value=\"ICMP\"/>\n" +
" </service-name>\n" +
" <status>\n" +
" <event-token is-parm=\"true\" name=\"passiveStatus\" value=\"Down\"/>\n" +
" </status>\n" +
" </status-key>\n" +
" </passive-event>\n" +
" </passive-events>\n" +
"</passive-status-configuration>\n" +
"";
}
@SuppressWarnings("unused")
private String getLiteralFieldConfig() {
return "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<this:passive-status-configuration \n" +
"xmlns:this=\"http://xmlns.opennms.org/xsd/passive-status-configuration\" \n" +
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" >\n" +
" <this:passive-events>\n" +
" <this:passive-event uei=\"uei.opennms.org/services/passiveServiceStatus\">\n" +
" <this:status-key>\n" +
" <this:node-label>\n" +
" <this:event-token is-parm=\"false\" name=\"host\" value=\"Router\"/>\n" +
" </this:node-label>\n" +
" <this:ipaddr>\n" +
" <this:event-token is-parm=\"false\" name=\"source\" value=\"192.168.1.1\"/>\n" +
" </this:ipaddr>\n" +
" <this:service-name>\n" +
" <this:event-token is-parm=\"false\" name=\"service\" value=\"ICMP\"/>\n" +
" </this:service-name>\n" +
" <this:status>\n" +
" <this:event-token is-parm=\"false\" name=\"descr\" value=\"Down\"/>\n" +
" </this:status>\n" +
" </this:status-key>\n" +
" </this:passive-event>\n" +
" </this:passive-events>\n" +
"</this:passive-status-configuration>\n" +
"";
}
@SuppressWarnings("unused")
private String getLiteralParmConfig() {
return "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<this:passive-status-configuration \n" +
"xmlns:this=\"http://xmlns.opennms.org/xsd/passive-status-configuration\" \n" +
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" >\n" +
" <this:passive-events>\n" +
" <this:passive-event uei=\"uei.opennms.org/services/passiveServiceStatus\">\n" +
" <this:status-key>\n" +
" <this:node-label>\n" +
" <this:event-token is-parm=\"true\" name=\"passiveNodeLabel\" value=\"Router\"/>\n" +
" </this:node-label>\n" +
" <this:ipaddr>\n" +
" <this:event-token is-parm=\"true\" name=\"passiveIpAddr\" value=\"192.168.1.1\"/>\n" +
" </this:ipaddr>\n" +
" <this:service-name>\n" +
" <this:event-token is-parm=\"true\" name=\"passiveServiceName\" value=\"ICMP\"/>\n" +
" </this:service-name>\n" +
" <this:status>\n" +
" <this:event-token is-parm=\"true\" name=\"passiveStatus\" value=\"Down\"/>\n" +
" </this:status>\n" +
" </this:status-key>\n" +
" </this:passive-event>\n" +
" </this:passive-events>\n" +
"</this:passive-status-configuration>\n" +
"";
}
@SuppressWarnings("unused")
private String getRegExFieldConfig() {
return "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<this:passive-status-configuration \n" +
"xmlns:this=\"http://xmlns.opennms.org/xsd/passive-status-configuration\" \n" +
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" >\n" +
" <this:passive-events>\n" +
" <this:passive-event uei=\"uei.opennms.org/services/passiveServiceStatus\">\n" +
" <this:status-key>\n" +
" <this:node-label>\n" +
" <this:event-token is-parm=\"false\" name=\"host\" value=\"~.*\"/>\n" +
" </this:node-label>\n" +
" <this:ipaddr>\n" +
" <this:event-token is-parm=\"false\" name=\"source\" value=\"~.*(192\\.168\\.1\\.1).*\"/>\n" +
" </this:ipaddr>\n" +
" <this:service-name>\n" +
" <this:event-token is-parm=\"false\" name=\"service\" value=\"~.*(ICMP).*\" format=\"$1\"/>\n" +
" </this:service-name>\n" +
" <this:status>\n" +
" <this:event-token is-parm=\"false\" name=\"descr\" value=\"~.*is(Down).*\" format=\"$1\"/>\n" +
" </this:status>\n" +
" </this:status-key>\n" +
" </this:passive-event>\n" +
" </this:passive-events>\n" +
"</this:passive-status-configuration>\n" +
"";
}
@SuppressWarnings("unused")
private String getRegExParmConfig() {
return "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<this:passive-status-configuration \n" +
"xmlns:this=\"http://xmlns.opennms.org/xsd/passive-status-configuration\" \n" +
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" >\n" +
" <translation>\n" +
" <event-translation-spec uei=\"uei.opennms.org/services/translationEvent\">\n" +
" <mappings>\n" +
" <mapping>\n" +
" <assignment type=\"field\" name=\"uei\">\n" +
" <value type=\"constant\" result=\"uei.opennms.org/services/passiveServiceStatus\" />\n" +
" </assignment>\n" +
" </mapping>\n" +
" </mappings>\n" +
" </event-translation-spec>\n" +
" </translation>\n" +
"</this:passive-status-configuration>\n" +
"";
}
}