diff --git a/src/main/java/net/floodlightcontroller/core/internal/Controller.java b/src/main/java/net/floodlightcontroller/core/internal/Controller.java index f9f44f460392d6fcfadb090af68556290461b6d1..e0559575f3353dc52173f8fb4c62f86e4d0d44e6 100644 --- a/src/main/java/net/floodlightcontroller/core/internal/Controller.java +++ b/src/main/java/net/floodlightcontroller/core/internal/Controller.java @@ -72,6 +72,8 @@ import net.floodlightcontroller.debugevent.IDebugEventService; import net.floodlightcontroller.debugevent.NullDebugEvent; import net.floodlightcontroller.debugevent.IDebugEventService.EventType; import net.floodlightcontroller.debugevent.IDebugEventService.MaxEventsRegistered; +import net.floodlightcontroller.notification.INotificationManager; +import net.floodlightcontroller.notification.NotificationManagerFactory; import net.floodlightcontroller.packet.Ethernet; import net.floodlightcontroller.packet.IPv4; import net.floodlightcontroller.perfmon.IPktInProcessingTimeService; @@ -84,7 +86,6 @@ import net.floodlightcontroller.threadpool.IThreadPoolService; import net.floodlightcontroller.util.EventHistory; import net.floodlightcontroller.util.LoadMonitor; import net.floodlightcontroller.util.EventHistory.EvAction; - import org.jboss.netty.bootstrap.ServerBootstrap; import org.jboss.netty.channel.ChannelPipelineFactory; import org.jboss.netty.channel.group.ChannelGroup; @@ -118,6 +119,8 @@ public class Controller implements IFloodlightProviderService, IStorageSourceListener { protected static Logger log = LoggerFactory.getLogger(Controller.class); + protected static INotificationManager notifier = + NotificationManagerFactory.getNotificationManager(Controller.class); static final String ERROR_DATABASE = "The controller could not communicate with the system database."; @@ -1138,6 +1141,7 @@ public class Controller implements IFloodlightProviderService, sw.cancelAllStatisticsReplies(); addUpdateToQueue(new SwitchUpdate(sw.getId(), SwitchUpdateType.REMOVED)); + notifier.postNotification("Switch " + sw.getStringId() + " disconnected."); } /** diff --git a/src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManager.java b/src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManager.java index d9f111171897a66bbffaeb825e6cac75878fe303..28b55a235ff46bf73ec765346b35b715ae6f46ab 100644 --- a/src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManager.java +++ b/src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManager.java @@ -72,6 +72,8 @@ import net.floodlightcontroller.linkdiscovery.ILinkDiscoveryListener; import net.floodlightcontroller.linkdiscovery.ILinkDiscoveryService; import net.floodlightcontroller.linkdiscovery.LinkInfo; import net.floodlightcontroller.linkdiscovery.web.LinkDiscoveryWebRoutable; +import net.floodlightcontroller.notification.INotificationManager; +import net.floodlightcontroller.notification.NotificationManagerFactory; import net.floodlightcontroller.packet.BSN; import net.floodlightcontroller.packet.Ethernet; import net.floodlightcontroller.packet.IPv4; @@ -122,6 +124,8 @@ public class LinkDiscoveryManager implements IOFMessageListener, IOFSwitchListener, IStorageSourceListener, ILinkDiscoveryService, IFloodlightModule, IInfoProvider { protected static final Logger log = LoggerFactory.getLogger(LinkDiscoveryManager.class); + protected static final INotificationManager notifier = + NotificationManagerFactory.getNotificationManager(LinkDiscoveryManager.class); public static final String MODULE_NAME = "linkdiscovery"; @@ -1328,6 +1332,7 @@ public class LinkDiscoveryManager implements IOFMessageListener, newInfo.getDstPortState(), linkType, EvAction.LINK_ADDED, "LLDP Recvd"); + notifier.postNotification("Link added: " + lt.toString()); } else { linkChanged = updateLink(lt, oldInfo, newInfo); if (linkChanged) { @@ -1345,6 +1350,7 @@ public class LinkDiscoveryManager implements IOFMessageListener, linkType, EvAction.LINK_PORT_STATE_UPDATED, "LLDP Recvd"); + notifier.postNotification("Link updated: " + lt.toString()); } } @@ -1465,6 +1471,8 @@ public class LinkDiscoveryManager implements IOFMessageListener, if (linkType == ILinkDiscovery.LinkType.DIRECT_LINK) { log.info("Inter-switch link removed: {}", lt); + notifier.postNotification("Inter-switch link removed: " + + lt.toString()); } else if (log.isTraceEnabled()) { log.trace("Deleted link {}", lt); } diff --git a/src/main/java/net/floodlightcontroller/notification/INotificationManager.java b/src/main/java/net/floodlightcontroller/notification/INotificationManager.java new file mode 100644 index 0000000000000000000000000000000000000000..7b5d87fc07178657d36cfb0d7c8072a0491f0250 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/notification/INotificationManager.java @@ -0,0 +1,23 @@ +package net.floodlightcontroller.notification; + +/** + * Base interface for managing notifications. + * + * Notification is used to alsert or inform notification receiver. + * Notification can be a message written into log file or an SNMP trap or + * SNMP notification. + * + * @author kevin.wang@bigswitch.com + * + */ +public interface INotificationManager { + + /** + * Post a notification. Depending on the underline implementation, it + * may write the notes to log file or send an SNMP notification/trap. + * + * @param notes string message to be sent to receiver + */ + public void postNotification(String notes); + +} diff --git a/src/main/java/net/floodlightcontroller/notification/INotificationManagerFactory.java b/src/main/java/net/floodlightcontroller/notification/INotificationManagerFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..270fb26f47673a6b0d3b58d86c1ebc294ed47972 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/notification/INotificationManagerFactory.java @@ -0,0 +1,18 @@ +package net.floodlightcontroller.notification; + +/** + * This factory interface produce INotificationManager instance. + * + * @author kevin.wang@bigswitch.com + * + */ +public interface INotificationManagerFactory { + + /** + * Produce and returns a NotificationManager based on the name + * + * @param clazz + * @return NotificationManager instance + */ + <T> INotificationManager getNotificationManager(Class<T> clazz); +} diff --git a/src/main/java/net/floodlightcontroller/notification/NotificationManagerFactory.java b/src/main/java/net/floodlightcontroller/notification/NotificationManagerFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..212c37a41fd24ab4ec0b3d1829f5d9da642d8be0 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/notification/NotificationManagerFactory.java @@ -0,0 +1,75 @@ +package net.floodlightcontroller.notification; + +import net.floodlightcontroller.notification.syslog.SyslogNotificationFactory; + +/** + * This factory is a public untility to get NotificationManager + * instance. + * + * @author kevinwang + * + */ +public class NotificationManagerFactory { + + public static final String NOTIFICATION_FACTORY_NAME = + "floodlight.notification.factoryName"; + + // default to SyslogNotificationFactory + private static INotificationManagerFactory + factory = new SyslogNotificationFactory(); + + /** + * Dynamically bind to a factory if there is one specified. + * This provides a simple and very basic implementation to override + * with a customized NotificationFactory. + * + */ + static { + NotificationManagerFactory.init(); + } + + /** + * A simple mechanism to initialize factory with dynamic binding + */ + protected static void init() { + String notificationfactoryClassName = null; + try { + notificationfactoryClassName = + System.getProperty(NOTIFICATION_FACTORY_NAME); + } catch (SecurityException e) { + e.printStackTrace(); + } + if (notificationfactoryClassName != null) { + Class<?> nfc; + try { + nfc = Class.forName(notificationfactoryClassName); + factory = (INotificationManagerFactory) nfc.newInstance(); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } catch (InstantiationException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + } + + /** + * Helper method to create a NotificationManager instance by class + * with the underline factory + * @param clazz + * @return + */ + public static <T> INotificationManager getNotificationManager(Class<T> clazz) { + return factory.getNotificationManager(clazz); + } + + /** + * Helper method to return the factory + * @return the INotificationManagerFactory instance + */ + public static <T> INotificationManagerFactory getNotificationManagerFactory() { + return factory; + } + +} diff --git a/src/main/java/net/floodlightcontroller/notification/syslog/SyslogNotificationFactory.java b/src/main/java/net/floodlightcontroller/notification/syslog/SyslogNotificationFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..62f7f976e17d5b962b619350b076170c9e34c231 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/notification/syslog/SyslogNotificationFactory.java @@ -0,0 +1,18 @@ +package net.floodlightcontroller.notification.syslog; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import net.floodlightcontroller.notification.INotificationManager; +import net.floodlightcontroller.notification.INotificationManagerFactory; + +public class SyslogNotificationFactory implements + INotificationManagerFactory { + + @Override + public <T> INotificationManager getNotificationManager(Class<T> clazz) { + Logger logger = LoggerFactory.getLogger(clazz.getCanonicalName() + ".syslog.notification"); + return new SyslogNotificationManager(logger); + } + +} diff --git a/src/main/java/net/floodlightcontroller/notification/syslog/SyslogNotificationManager.java b/src/main/java/net/floodlightcontroller/notification/syslog/SyslogNotificationManager.java new file mode 100644 index 0000000000000000000000000000000000000000..5d5efdb4e0c9d7587a09df41c279bea4443f3ba3 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/notification/syslog/SyslogNotificationManager.java @@ -0,0 +1,20 @@ +package net.floodlightcontroller.notification.syslog; + +import org.slf4j.Logger; + +import net.floodlightcontroller.notification.INotificationManager; + +public class SyslogNotificationManager implements INotificationManager { + + private final Logger logger; + + public SyslogNotificationManager(Logger logger) { + this.logger = logger; + } + + @Override + public void postNotification(String notes) { + logger.warn(notes); + } + +} diff --git a/src/test/java/net/floodlightcontroller/notification/MockNotificationManagerFactory.java b/src/test/java/net/floodlightcontroller/notification/MockNotificationManagerFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..9e49c20161db7d1557ac76770a5f9e5989446681 --- /dev/null +++ b/src/test/java/net/floodlightcontroller/notification/MockNotificationManagerFactory.java @@ -0,0 +1,11 @@ +package net.floodlightcontroller.notification; + +public class MockNotificationManagerFactory implements + INotificationManagerFactory { + + @Override + public <T> INotificationManager getNotificationManager(Class<T> clazz) { + return null; + } + +} diff --git a/src/test/java/net/floodlightcontroller/notification/NotificationTest.java b/src/test/java/net/floodlightcontroller/notification/NotificationTest.java new file mode 100644 index 0000000000000000000000000000000000000000..312c602b5a3cebafb4047186ad456b232c84dfc2 --- /dev/null +++ b/src/test/java/net/floodlightcontroller/notification/NotificationTest.java @@ -0,0 +1,20 @@ +package net.floodlightcontroller.notification; + +import junit.framework.Assert; + +import org.junit.Test; + +public class NotificationTest { + + @Test + public void testDynamicBinding() { + System.setProperty(NotificationManagerFactory.NOTIFICATION_FACTORY_NAME, + "net.floodlightcontroller.notification.MockNotificationManagerFactory"); + NotificationManagerFactory.init(); + INotificationManagerFactory factory = + NotificationManagerFactory.getNotificationManagerFactory(); + Assert.assertNotNull(factory); + Assert.assertTrue(factory instanceof MockNotificationManagerFactory); + } + +}