[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);
+ }
+
+}