/******************************************************************************* * 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.config; import static org.junit.Assert.assertEquals; import static org.opennms.core.utils.InetAddressUtils.addr; import java.io.IOException; import javax.sql.DataSource; import org.exolab.castor.xml.MarshalException; import org.exolab.castor.xml.ValidationException; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.opennms.core.test.OpenNMSJUnit4ClassRunner; import org.opennms.core.utils.BeanUtils; import org.opennms.netmgt.config.notifications.Notification; import org.opennms.netmgt.dao.CategoryDao; import org.opennms.netmgt.dao.IpInterfaceDao; import org.opennms.netmgt.dao.MonitoredServiceDao; import org.opennms.netmgt.dao.NodeDao; import org.opennms.netmgt.dao.ServiceTypeDao; import org.opennms.netmgt.dao.db.JUnitConfigurationEnvironment; import org.opennms.netmgt.dao.db.JUnitTemporaryDatabase; import org.opennms.netmgt.dao.db.TemporaryDatabase; import org.opennms.netmgt.dao.db.TemporaryDatabaseAware; import org.opennms.netmgt.dao.support.JdbcFilterDao; import org.opennms.netmgt.filter.FilterDaoFactory; import org.opennms.netmgt.filter.FilterParseException; import org.opennms.netmgt.model.OnmsCategory; import org.opennms.netmgt.model.OnmsDistPoller; import org.opennms.netmgt.model.OnmsIpInterface; import org.opennms.netmgt.model.OnmsMonitoredService; import org.opennms.netmgt.model.OnmsNode; import org.opennms.netmgt.model.OnmsServiceType; import org.opennms.netmgt.model.events.EventBuilder; import org.opennms.netmgt.notifd.mock.MockNotifdConfigManager; import org.opennms.test.ConfigurationTestUtils; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; @RunWith(OpenNMSJUnit4ClassRunner.class) @ContextConfiguration(locations={ "classpath:/META-INF/opennms/applicationContext-dao.xml", "classpath*:/META-INF/opennms/component-dao.xml" }) @JUnitConfigurationEnvironment @JUnitTemporaryDatabase public class NotificationManagerTest implements TemporaryDatabaseAware<TemporaryDatabase>, InitializingBean { @Autowired private DataSource m_dataSource; @Autowired private NodeDao m_nodeDao; @Autowired private IpInterfaceDao m_ipInterfaceDao; @Autowired private MonitoredServiceDao m_serviceDao; @Autowired private ServiceTypeDao m_serviceTypeDao; @Autowired private CategoryDao m_categoryDao; private NotificationManagerImpl m_notificationManager; private NotifdConfigManager m_configManager; private TemporaryDatabase m_database; @Override public void setTemporaryDatabase(TemporaryDatabase database) { m_database = database; } @Override public void afterPropertiesSet() throws Exception { BeanUtils.assertAutowiring(this); } @Before public void setUp() throws Exception { // Initialize Filter DAO DatabaseSchemaConfigFactory.init(); JdbcFilterDao jdbcFilterDao = new JdbcFilterDao(); jdbcFilterDao.setDataSource(m_database); jdbcFilterDao.setDatabaseSchemaConfigFactory(DatabaseSchemaConfigFactory.getInstance()); jdbcFilterDao.afterPropertiesSet(); FilterDaoFactory.setInstance(jdbcFilterDao); m_configManager = new MockNotifdConfigManager(ConfigurationTestUtils.getConfigForResourceWithReplacements(this, "notifd-configuration.xml")); m_notificationManager = new NotificationManagerImpl(m_configManager, m_dataSource); final OnmsDistPoller distPoller = new OnmsDistPoller("localhost", "127.0.0.1"); OnmsNode node; OnmsIpInterface ipInterface; OnmsMonitoredService service; OnmsServiceType serviceType; OnmsCategory category1 = new OnmsCategory("CategoryOne"); m_categoryDao.save(category1); OnmsCategory category2 = new OnmsCategory("CategoryTwo"); m_categoryDao.save(category2); OnmsCategory category3 = new OnmsCategory("CategoryThree"); m_categoryDao.save(category3); OnmsCategory category4 = new OnmsCategory("CategoryFour"); m_categoryDao.save(category4); m_categoryDao.flush(); // node 1 serviceType = new OnmsServiceType("HTTP"); m_serviceTypeDao.save(serviceType); node = new OnmsNode(distPoller, "node 1"); node.addCategory(category1); node.addCategory(category2); node.addCategory(category3); ipInterface = new OnmsIpInterface("192.168.1.1", node); service = new OnmsMonitoredService(ipInterface, serviceType); m_nodeDao.save(node); // node 2 node = new OnmsNode(distPoller, "node 2"); node.addCategory(category1); node.addCategory(category2); node.addCategory(category4); m_nodeDao.save(node); ipInterface = new OnmsIpInterface("192.168.1.1", node); m_ipInterfaceDao.save(ipInterface); service = new OnmsMonitoredService(ipInterface, serviceType); m_serviceDao.save(service); ipInterface = new OnmsIpInterface("0.0.0.0", node); m_ipInterfaceDao.save(ipInterface); // node 3 node = new OnmsNode(distPoller, "node 3"); m_nodeDao.save(node); ipInterface = new OnmsIpInterface("192.168.1.2", node); m_ipInterfaceDao.save(ipInterface); service = new OnmsMonitoredService(ipInterface, serviceType); m_serviceDao.save(service); // node 4 has an interface, but no services node = new OnmsNode(distPoller, "node 4"); m_nodeDao.save(node); ipInterface = new OnmsIpInterface("192.168.1.3", node); m_ipInterfaceDao.save(ipInterface); // node 5 has no interfaces node = new OnmsNode(distPoller, "node 5"); m_nodeDao.save(node); m_nodeDao.flush(); m_ipInterfaceDao.flush(); m_serviceDao.flush(); m_serviceTypeDao.flush(); m_categoryDao.flush(); } @Test @JUnitTemporaryDatabase // Relies on specific IDs so we need a fresh database public void testNoElement() { doTestNodeInterfaceServiceWithRule("node/interface/service match", 0, null, null, "(ipaddr IPLIKE *.*.*.*)", true); } /** * This should match because even though the node is not set in the event, * the IP address is in the database on *some* node. */ @Test @JUnitTemporaryDatabase // Relies on specific IDs so we need a fresh database public void testNoNodeIdWithIpAddr() { doTestNodeInterfaceServiceWithRule("node/interface/service match", 0, "192.168.1.1", null, "(ipaddr == '192.168.1.1')", true); } /** * Trapd sends events like this (with no nodeId set but an interface set) * when it gets a trap from a device with an IP that isn't in the * database. This shouldn't send an event. */ @Test @JUnitTemporaryDatabase // Relies on specific IDs so we need a fresh database public void testNoNodeIdWithIpAddrNotInDb() { doTestNodeInterfaceServiceWithRule("node/interface/service match", 0, "192.168.1.2", null, "(ipaddr == '192.168.1.1')", false); } /** * This should match because even though the node is not set in the event, * the IP address and service is in the database on *some* node. */ @Test @JUnitTemporaryDatabase // Relies on specific IDs so we need a fresh database public void testNoNodeIdWithService() { doTestNodeInterfaceServiceWithRule("node/interface/service match", 0, null, "HTTP", "(ipaddr == '192.168.1.1')", true); } // FIXME... do we really want to return true if the rule is wrong????? @Test @JUnitTemporaryDatabase // Relies on specific IDs so we need a fresh database public void testRuleBogus() { try { doTestNodeInterfaceServiceWithRule("node/interface/service match", 1, "192.168.1.1", "HTTP", "(aklsdfjweklj89jaikj)", false); Assert.fail("Expected exception to be thrown!"); } catch (FilterParseException e) { // I expected this } } @Test @JUnitTemporaryDatabase // Relies on specific IDs so we need a fresh database public void testIplikeAllStars() { doTestNodeInterfaceServiceWithRule("node/interface/service match", 1, "192.168.1.1", "HTTP", "(ipaddr IPLIKE *.*.*.*)", true); } @Test @JUnitTemporaryDatabase // Relies on specific IDs so we need a fresh database public void testNodeOnlyMatch() { doTestNodeInterfaceServiceWithRule("node/interface/service match", 1, null, null, "(ipaddr == '192.168.1.1')", true); } @Test @JUnitTemporaryDatabase // Relies on specific IDs so we need a fresh database public void testNodeOnlyMatchZeroesIpAddr() { doTestNodeInterfaceServiceWithRule("node/interface/service match", 1, "0.0.0.0", null, "(ipaddr == '192.168.1.1')", true); } @Test @JUnitTemporaryDatabase // Relies on specific IDs so we need a fresh database public void testNodeOnlyNoMatch() { doTestNodeInterfaceServiceWithRule("node/interface/service match", 3, null, null, "(ipaddr == '192.168.1.1')", false); } @Test @JUnitTemporaryDatabase // Relies on specific IDs so we need a fresh database public void testWrongNodeId() throws InterruptedException { doTestNodeInterfaceServiceWithRule("node/interface/service match", 2, "192.168.1.1", "HTTP", "(nodeid == 1)", false); } @Test @JUnitTemporaryDatabase // Relies on specific IDs so we need a fresh database public void testIpAddrSpecificPass() throws InterruptedException { doTestNodeInterfaceServiceWithRule("node/interface/service match", 1, "192.168.1.1", null, "(ipaddr == '192.168.1.1')", true); } @Test @JUnitTemporaryDatabase // Relies on specific IDs so we need a fresh database public void testIpAddrSpecificFail() { doTestNodeInterfaceServiceWithRule("node/interface/service match", 1, "192.168.1.1", null, "(ipaddr == '192.168.1.2')", false); } @Test @JUnitTemporaryDatabase // Relies on specific IDs so we need a fresh database public void testIpAddrServiceSpecificPass() throws InterruptedException { doTestNodeInterfaceServiceWithRule("node/interface/service match", 1, "192.168.1.1", "HTTP", "(ipaddr == '192.168.1.1')", true); } @Test @JUnitTemporaryDatabase // Relies on specific IDs so we need a fresh database public void testIpAddrServiceSpecificFail() { doTestNodeInterfaceServiceWithRule("node/interface/service match", 1, "192.168.1.1", "HTTP", "(ipaddr == '192.168.1.2')", false); } @Test @JUnitTemporaryDatabase // Relies on specific IDs so we need a fresh database public void testIpAddrServiceSpecificWrongService() { doTestNodeInterfaceServiceWithRule("node/interface/service match", 1, "192.168.1.1", "ICMP", "(ipaddr == '192.168.1.1')", false); } @Test @JUnitTemporaryDatabase // Relies on specific IDs so we need a fresh database public void testIpAddrServiceSpecificWrongIP() { doTestNodeInterfaceServiceWithRule("node/interface/service match", 1, "192.168.1.2", "HTTP", "(ipaddr == '192.168.1.1')", false); } @Test @JUnitTemporaryDatabase // Relies on specific IDs so we need a fresh database public void testMultipleCategories() { doTestNodeInterfaceServiceWithRule("node/interface/service match", 1, "192.168.1.1", "HTTP", "(catincCategoryOne) & (catincCategoryTwo) & (catincCategoryThree)", true); } @Test @JUnitTemporaryDatabase // Relies on specific IDs so we need a fresh database public void testMultipleCategoriesNotMember() throws InterruptedException { doTestNodeInterfaceServiceWithRule("node/interface/service match", 2, "192.168.1.1", "HTTP", "(catincCategoryOne) & (catincCategoryTwo) & (catincCategoryThree)", false); } @Test @JUnitTemporaryDatabase // Relies on specific IDs so we need a fresh database public void testIpAddrMatchWithNoServiceOnInterface() { doTestNodeInterfaceServiceWithRule("node/interface/service match", 4, null, null, "(ipaddr == '192.168.1.3')", true); } /** * This test returns false because the ipInterface table is the * "primary" table in database-schema.xml, so it is joined with * every query, even if we don't ask for it to be joined and if * it isn't referenced in the filter query. Sucky, huh? */ @Test @JUnitTemporaryDatabase // Relies on specific IDs so we need a fresh database public void testNodeMatchWithNoInterfacesOnNode() { doTestNodeInterfaceServiceWithRule("node/interface/service match", 5, null, null, "(nodeId == 5)", false); } /** * This tests bugzilla bug #1807. The problem happened when we add our * own constraints to the filter but fail to wrap the user's filter in * parens. This isn't a problem when the outermost logic expression in * the user's filter (if any) is an AND, but it is if it's an OR. */ @Test @JUnitTemporaryDatabase // Relies on specific IDs so we need a fresh database public void testRuleWithOrNoMatch() { /* * Note: the nodeLabel for nodeId=3/ipAddr=192.168.1.2 is 'node 3' * which shouldn't match the filter. */ doTestNodeInterfaceServiceWithRule("node/interface/service match", 3, "192.168.1.2", "HTTP", "(nodelabel=='node 1') | (nodelabel=='node 2')", false); } private void doTestNodeInterfaceServiceWithRule(String description, int nodeId, String intf, String svc, String rule, boolean matches) { Notification notif = new Notification(); notif.setName("a notification"); notif.setRule(rule); EventBuilder builder = new EventBuilder("uei.opennms.org/doNotCareAboutTheUei", "Test.Event"); builder.setNodeid(nodeId); builder.setInterface(addr(intf)); builder.setService(svc); assertEquals(description, matches, m_notificationManager.nodeInterfaceServiceValid(notif, builder.getEvent())); } public static class NotificationManagerImpl extends NotificationManager { protected NotificationManagerImpl(NotifdConfigManager configManager, DataSource dcf) { super(configManager, dcf); } @Override protected void saveXML(String xmlString) throws IOException { return; } @Override public void update() throws IOException, MarshalException, ValidationException { return; } } }