[ONOS-3203] End-to-end demo of Fault Management via SNMP.

This adds SNMP device-discovery, and a Fault Management app which makes alarms available to users via REST/GUI/CLI interfaces.
There is still code cleanup that could be done, but aim of this commit is an end-to-end proof of concept.

To demonstrate :

1) /opt/onos/bin/onos-service
onos> app activate org.onosproject.snmp
onos> app activate org.onosproject.faultmanagement

2) SNMP devices are seeded via config file. The default seed file contains connection details for devices (SNMP agents) available via internet  e.g. demo.snmplabs.com
cp /opt/onos/apache-karaf-3.0.3/etc/samples/org.onosproject.provider.snmp.device.impl.SnmpDeviceProvider.cfg   /opt/onos/apache-karaf-3.0.3/etc/

3) ONOS will poll these SNMP devices and store their alarms.

4) You can now manipulate the alarms via REST  e.g. http://<onos>:8181/onos/v1/fm/alarms , via CLI  via various "alarm-*” commands or in UI with an Alarms Overlay.

More info at https://wiki.onosproject.org/display/ONOS/Fault+Management

15/Dec/15: Updated regarding review comments from Thomas Vachuska.
17/Dec/15: Updated coreService.registerApplication(name) as per https://gerrit.onosproject.org/#/c/6878/

Change-Id: I886f8511f178dc4600ab96e5ff10cc90329cabec
diff --git a/providers/snmp/alarm/src/test/java/org/onosproject/provider/snmp/alarm/impl/Bti7000SnmpAlarmProviderTest.java b/providers/snmp/alarm/src/test/java/org/onosproject/provider/snmp/alarm/impl/Bti7000SnmpAlarmProviderTest.java
new file mode 100644
index 0000000..f26100c
--- /dev/null
+++ b/providers/snmp/alarm/src/test/java/org/onosproject/provider/snmp/alarm/impl/Bti7000SnmpAlarmProviderTest.java
@@ -0,0 +1,115 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.provider.snmp.alarm.impl;
+
+import com.btisystems.mibbler.mibs.bti7000.bti7000_13_2_0.btisystems.btiproducts.bti7000.objects.conditions.ActAlarmTable;
+import com.btisystems.mibbler.mibs.bti7000.interfaces.btisystems.btiproducts.bti7000.objects.conditions.actalarmtable.IActAlarmEntry;
+import com.btisystems.pronx.ems.core.model.NetworkDevice;
+import com.btisystems.pronx.ems.core.snmp.ISnmpSession;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Arrays;
+import java.util.Collection;
+import org.easymock.Capture;
+import static org.easymock.EasyMock.capture;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.eq;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.isA;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.*;
+import org.onosproject.incubator.net.faultmanagement.alarm.Alarm;
+import org.onosproject.net.DeviceId;
+import org.snmp4j.smi.OID;
+
+
+public class Bti7000SnmpAlarmProviderTest {
+    private Bti7000SnmpAlarmProvider alarmProvider;
+    private ISnmpSession mockSession;
+    private ActAlarmTable alarmsTable;
+
+    public Bti7000SnmpAlarmProviderTest() {
+    }
+
+    @Before
+    public void setUp() {
+        mockSession = createMock(ISnmpSession.class);
+
+        alarmProvider = new Bti7000SnmpAlarmProvider();
+    }
+
+    @Test
+    public void shouldWalkDevice() throws UnknownHostException, IOException {
+        expect(mockSession.getAddress()).andReturn(InetAddress.getLoopbackAddress());
+        expect(mockSession.walkDevice(isA(NetworkDevice.class),
+                eq(Arrays.asList(new OID[]{
+                    Bti7000SnmpAlarmProvider.CLASS_REGISTRY.getClassToOidMap().get(ActAlarmTable.class)}))))
+                .andReturn(null);
+
+        replay(mockSession);
+
+        assertNotNull(alarmProvider.getAlarms(mockSession, DeviceId.deviceId("snmp:1.1.1.1")));
+
+        verify(mockSession);
+    }
+
+    @Test
+    public void shouldFindAlarms() throws UnknownHostException, IOException {
+        alarmsTable = new ActAlarmTable();
+        alarmsTable.createEntry("14.1.3.6.1.4.1.18070.2.2.2.2.20.0.1.13.1.3.6.1.4.1."
+                + "18070.2.2.1.4.14.1.7.49.46.55.46.50.46.53");
+        IActAlarmEntry entry = alarmsTable.getEntries().values().iterator().next();
+        entry.setActAlarmDescription("XFP Missing.");
+        entry.setActAlarmDateAndTime("07:df:0c:01:03:0d:30:00");
+        entry.setActAlarmSeverity(1);
+
+        Capture<NetworkDevice> networkDeviceCapture = new Capture<>();
+
+        expect(mockSession.getAddress()).andReturn(InetAddress.getLoopbackAddress());
+        expect(mockSession.walkDevice(capture(networkDeviceCapture),
+                eq(Arrays.asList(new OID[]{
+                    Bti7000SnmpAlarmProvider.CLASS_REGISTRY.getClassToOidMap().get(ActAlarmTable.class)}))))
+                .andAnswer(() -> {
+                    networkDeviceCapture.getValue().getRootObject().setObject(alarmsTable);
+                    return null;
+        });
+
+        replay(mockSession);
+
+        Collection<Alarm> alarms = alarmProvider.getAlarms(mockSession, DeviceId.deviceId("snmp:1.1.1.1"));
+        assertEquals(1, alarms.size());
+        assertEquals("XFP Missing.", alarms.iterator().next().description());
+        verify(mockSession);
+    }
+
+    @Test
+    public void shouldHandleException() throws UnknownHostException, IOException {
+        expect(mockSession.getAddress()).andReturn(InetAddress.getLoopbackAddress());
+        expect(mockSession.walkDevice(isA(NetworkDevice.class),
+                eq(Arrays.asList(new OID[]{
+                    Bti7000SnmpAlarmProvider.CLASS_REGISTRY.getClassToOidMap().get(ActAlarmTable.class)}))))
+                .andThrow(new IOException());
+
+        replay(mockSession);
+
+        assertNotNull(alarmProvider.getAlarms(mockSession, DeviceId.deviceId("snmp:1.1.1.1")));
+
+        verify(mockSession);
+    }
+
+}
diff --git a/providers/snmp/alarm/src/test/java/org/onosproject/provider/snmp/alarm/impl/NetSnmpSnmpAlarmProviderTest.java b/providers/snmp/alarm/src/test/java/org/onosproject/provider/snmp/alarm/impl/NetSnmpSnmpAlarmProviderTest.java
new file mode 100644
index 0000000..1442e8d
--- /dev/null
+++ b/providers/snmp/alarm/src/test/java/org/onosproject/provider/snmp/alarm/impl/NetSnmpSnmpAlarmProviderTest.java
@@ -0,0 +1,114 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.provider.snmp.alarm.impl;
+
+import com.btisystems.mibbler.mibs.netsnmp.interfaces.mib_2.interfaces.iftable.IIfEntry;
+import com.btisystems.mibbler.mibs.netsnmp.netsnmp.mib_2.interfaces.IfTable;
+import com.btisystems.pronx.ems.core.model.NetworkDevice;
+import com.btisystems.pronx.ems.core.snmp.ISnmpSession;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Arrays;
+import java.util.Collection;
+import org.easymock.Capture;
+import static org.easymock.EasyMock.capture;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.eq;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.isA;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.*;
+import org.onosproject.incubator.net.faultmanagement.alarm.Alarm;
+import org.onosproject.net.DeviceId;
+import org.snmp4j.smi.OID;
+
+
+public class NetSnmpSnmpAlarmProviderTest {
+    private NetSnmpAlarmProvider alarmProvider;
+    private ISnmpSession mockSession;
+    private IfTable interfaceTable;
+
+    public NetSnmpSnmpAlarmProviderTest() {
+    }
+
+    @Before
+    public void setUp() {
+        mockSession = createMock(ISnmpSession.class);
+
+        alarmProvider = new NetSnmpAlarmProvider();
+    }
+
+    @Test
+    public void shouldWalkDevice() throws UnknownHostException, IOException {
+        expect(mockSession.getAddress()).andReturn(InetAddress.getLoopbackAddress());
+        expect(mockSession.walkDevice(isA(NetworkDevice.class),
+                eq(Arrays.asList(new OID[]{
+                    NetSnmpAlarmProvider.CLASS_REGISTRY.getClassToOidMap().get(IfTable.class)}))))
+                .andReturn(null);
+
+        replay(mockSession);
+
+        assertNotNull(alarmProvider.getAlarms(mockSession, DeviceId.deviceId("snmp:1.1.1.1")));
+
+        verify(mockSession);
+    }
+
+    @Test
+    public void shouldFindAlarms() throws UnknownHostException, IOException {
+        interfaceTable = new IfTable();
+        interfaceTable.createEntry("1");
+        IIfEntry entry = interfaceTable.getEntry("1");
+        entry.setIfDescr("eth1");
+        entry.setIfAdminStatus(1);
+        entry.setIfOperStatus(2);
+
+        Capture<NetworkDevice> networkDeviceCapture = new Capture<>();
+
+        expect(mockSession.getAddress()).andReturn(InetAddress.getLoopbackAddress());
+        expect(mockSession.walkDevice(capture(networkDeviceCapture),
+                eq(Arrays.asList(new OID[]{
+                    NetSnmpAlarmProvider.CLASS_REGISTRY.getClassToOidMap().get(IfTable.class)}))))
+                .andAnswer(() -> {
+                    networkDeviceCapture.getValue().getRootObject().setObject(interfaceTable);
+                    return null;
+        });
+
+        replay(mockSession);
+
+        Collection<Alarm> alarms = alarmProvider.getAlarms(mockSession, DeviceId.deviceId("snmp:1.1.1.1"));
+        assertEquals(1, alarms.size());
+        assertEquals("Link Down.", alarms.iterator().next().description());
+        verify(mockSession);
+    }
+
+    @Test
+    public void shouldHandleException() throws UnknownHostException, IOException {
+        expect(mockSession.getAddress()).andReturn(InetAddress.getLoopbackAddress());
+        expect(mockSession.walkDevice(isA(NetworkDevice.class),
+                eq(Arrays.asList(new OID[]{
+                    NetSnmpAlarmProvider.CLASS_REGISTRY.getClassToOidMap().get(IfTable.class)}))))
+                .andThrow(new IOException());
+
+        replay(mockSession);
+
+        assertNotNull(alarmProvider.getAlarms(mockSession, DeviceId.deviceId("snmp:1.1.1.1")));
+
+        verify(mockSession);
+    }
+
+}
diff --git a/providers/snmp/alarm/src/test/java/org/onosproject/provider/snmp/alarm/impl/SnmpDeviceAlarmProviderTest.java b/providers/snmp/alarm/src/test/java/org/onosproject/provider/snmp/alarm/impl/SnmpDeviceAlarmProviderTest.java
new file mode 100644
index 0000000..f443831
--- /dev/null
+++ b/providers/snmp/alarm/src/test/java/org/onosproject/provider/snmp/alarm/impl/SnmpDeviceAlarmProviderTest.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.provider.snmp.alarm.impl;
+
+import com.btisystems.pronx.ems.core.snmp.ISnmpConfiguration;
+import com.btisystems.pronx.ems.core.snmp.ISnmpSession;
+import com.btisystems.pronx.ems.core.snmp.ISnmpSessionFactory;
+import java.io.IOException;
+import java.util.HashSet;
+import org.easymock.EasyMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.onosproject.incubator.net.faultmanagement.alarm.AlarmEvent;
+import org.onosproject.net.DeviceId;
+
+public class SnmpDeviceAlarmProviderTest {
+    private SnmpAlarmProviderService alarmProvider;
+    private ISnmpSessionFactory mockSessionFactory;
+    private ISnmpSession mockSession;
+    private SnmpDeviceAlarmProvider mockProvider;
+    private AlarmEvent alarmEvent;
+
+    public SnmpDeviceAlarmProviderTest() {}
+
+    @Before
+    public void setUp() {
+        mockSessionFactory = EasyMock.createMock(ISnmpSessionFactory.class);
+        mockSession = EasyMock.createMock(ISnmpSession.class);
+        mockProvider = EasyMock.createMock(SnmpDeviceAlarmProvider.class);
+
+        alarmProvider = new SnmpAlarmProviderService() {
+            @Override
+            protected ISnmpSessionFactory getSessionFactory() {
+                return mockSessionFactory;
+            }
+        };
+
+        alarmProvider.addAlarmListener((AlarmEvent event) -> {
+            alarmEvent = event;
+        });
+    }
+
+    @Test
+    public void shouldPopulateAlarmsForNetSnmp() throws IOException {
+        alarmProvider.providers.put("1.2.3.4", mockProvider);
+        expect(mockSessionFactory.createSession(EasyMock.isA(ISnmpConfiguration.class),
+                EasyMock.eq("1.1.1.1"))).andReturn(mockSession);
+        expect(mockSession.identifyDevice()).andReturn("1.2.3.4");
+        expect(mockProvider.getAlarms(mockSession, DeviceId.deviceId("snmp:1.1.1.1:161")))
+                .andReturn(new HashSet<>());
+
+        mockSession.close();
+        EasyMock.expectLastCall().once();
+
+        replay(mockSessionFactory, mockSession, mockProvider);
+
+        alarmProvider.triggerProbe(DeviceId.deviceId("snmp:1.1.1.1:161"));
+
+        verify(mockSessionFactory, mockSession, mockProvider);
+        Assert.assertNotNull(alarmEvent);
+    }
+
+}