Andrea Campanella
Committed by Gerrit Code Review

[ONOS-4260]Alarm and fault managment application refactoring according to ONOS architecture

Change-Id: I47e9db37eb5fc27ac19db2e4cb87774736b44685
Showing 30 changed files with 592 additions and 224 deletions
......@@ -76,7 +76,6 @@ CORE = [
'//providers/pcep/topology:onos-pcep-provider-topology',
'//providers/pcep/tunnel:onos-pcep-provider-tunnel',
'//providers/rest/device:onos-restsb-provider-device',
'//providers/snmp/alarm:onos-snmp-provider-alarm',
'//providers/snmp/device:onos-snmp-provider-device',
'//web/api:onos-rest',
......
......@@ -35,9 +35,9 @@ public class GetAllAlarmsCounts extends AbstractShellCommand {
printCounts(alarmCounts);
}
static void printCounts(Map<Alarm.SeverityLevel, Long> alarmCounts) {
void printCounts(Map<Alarm.SeverityLevel, Long> alarmCounts) {
alarmCounts.entrySet().stream().forEach((countEntry) -> {
System.out.println(String.format("%s, %d",
print(String.format("%s, %d",
countEntry.getKey(), countEntry.getValue()));
});
......
......@@ -38,7 +38,14 @@ public class GetDeviceAlarmsCounts extends AbstractShellCommand {
Map<Alarm.SeverityLevel, Long> alarmCounts = AbstractShellCommand.get(AlarmService.class).
getAlarmCounts(DeviceId.deviceId(deviceId));
// Deliberately using same formatting for both ...
GetAllAlarmsCounts.printCounts(alarmCounts);
printCounts(alarmCounts);
}
void printCounts(Map<Alarm.SeverityLevel, Long> alarmCounts) {
alarmCounts.entrySet().stream().forEach((countEntry) -> {
print(String.format("%s, %d",
countEntry.getKey(), countEntry.getValue()));
});
}
}
......
......@@ -42,7 +42,7 @@ import org.onosproject.incubator.net.faultmanagement.alarm.Alarm;
import org.onosproject.incubator.net.faultmanagement.alarm.AlarmService;
/**
* Skeletal ONOS UI Topology-Overlay message handler.
* FaultManagement UI Topology-Overlay message handler.
*/
public class AlarmTopovMessageHandler extends UiMessageHandler {
......
......@@ -45,11 +45,6 @@
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-snmp-provider-alarm</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.compendium</artifactId>
<version>5.0.0</version>
......
......@@ -15,109 +15,136 @@
*/
package org.onosproject.faultmanagement.impl;
import com.google.common.collect.Sets;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import com.google.common.collect.ImmutableSet;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import static org.junit.Assert.*;
import org.junit.rules.ExpectedException;
import org.onlab.util.ItemNotFoundException;
import org.onosproject.net.DeviceId;
import static org.hamcrest.Matchers.containsString;
import org.onosproject.incubator.net.faultmanagement.alarm.Alarm;
import static org.onosproject.incubator.net.faultmanagement.alarm.Alarm.SeverityLevel.*;
import org.onosproject.incubator.net.faultmanagement.alarm.AlarmEntityId;
import org.onosproject.incubator.net.faultmanagement.alarm.AlarmId;
import org.onosproject.incubator.net.faultmanagement.alarm.DefaultAlarm;
import org.onosproject.net.DeviceId;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.onosproject.incubator.net.faultmanagement.alarm.Alarm.SeverityLevel.CLEARED;
import static org.onosproject.incubator.net.faultmanagement.alarm.Alarm.SeverityLevel.CRITICAL;
/**
* Alarm manager test suite.
*/
public class AlarmsManagerTest {
private static final DeviceId DEVICE_ID = DeviceId.deviceId("foo:bar");
private static final DefaultAlarm ALARM_A = new DefaultAlarm.Builder(
DEVICE_ID, "aaa", Alarm.SeverityLevel.CRITICAL, 0).build();
private static final DefaultAlarm ALARM_A_WITHSRC = new DefaultAlarm.Builder(
ALARM_A).forSource(AlarmEntityId.alarmEntityId("port:foo")).build();
private static final DefaultAlarm ALARM_B = new DefaultAlarm.Builder(
DEVICE_ID, "bbb", Alarm.SeverityLevel.CRITICAL, 0).build();
private AlarmsManager am;
@Rule
public final ExpectedException exception = ExpectedException.none();
@Before
public void setUp() throws Exception {
am = new AlarmsManager();
}
@Test
public void deactivate() throws Exception {
am.updateAlarms(DEVICE_ID, ImmutableSet.of(ALARM_B, ALARM_A));
verifyGettingSetsOfAlarms(am, 2, 2);
am.deactivate(null);
assertEquals("Alarms should be purged", 0, am.alarms.size());
}
@Test
public void testGettersWhenNoAlarms() {
AlarmsManager am = new AlarmsManager();
assertTrue("No alarms", am.getAlarms().isEmpty());
assertTrue("No active alarms", am.getActiveAlarms().isEmpty());
assertTrue("No alarms gives empty map per unknown device", am.getAlarmCounts(DeviceId.NONE).keySet().isEmpty());
assertTrue("No alarms gives empty map", am.getAlarmCounts().keySet().isEmpty());
assertEquals("Zero alarms for that device", 0, am.getAlarms(DeviceId.NONE).size());
assertEquals("Zero major alarms", 0, am.getAlarms(Alarm.SeverityLevel.MAJOR).size());
try {
assertEquals("no alarms", 0, am.getAlarm(null));
} catch (NullPointerException ex) {
assertThat(ex.getMessage(),
containsString("cannot be null"));
}
try {
assertEquals("no alarms", 0, am.getAlarm(AlarmId.alarmId(1)));
} catch (ItemNotFoundException ex) {
assertThat(ex.getMessage(),
containsString("not found"));
}
assertTrue("No alarms should be present", am.getAlarms().isEmpty());
assertTrue("No active alarms should be present", am.getActiveAlarms().isEmpty());
assertTrue("The map should be empty per unknown device",
am.getAlarmCounts(DeviceId.NONE).keySet().isEmpty());
assertTrue("The counts should be empty", am.getAlarmCounts().keySet().isEmpty());
assertEquals("Incorrect number of alarms for unknown device",
0, am.getAlarms(DeviceId.NONE).size());
assertEquals("Incorrect number of major alarms for unknown device",
0, am.getAlarms(Alarm.SeverityLevel.MAJOR).size());
exception.expect(NullPointerException.class);
am.getAlarm(null);
exception.expect(ItemNotFoundException.class);
am.getAlarm(AlarmId.alarmId(1));
}
@Test
public void testAlarmUpdates() {
AlarmsManager am = new AlarmsManager();
assertTrue("no alarms", am.getAlarms().isEmpty());
am.updateAlarms(new HashSet<>(), DEVICE_ID);
assertTrue("still no alarms", am.getAlarms().isEmpty());
assertTrue("No alarms should be present", am.getAlarms().isEmpty());
am.updateAlarms(DEVICE_ID, ImmutableSet.of());
assertTrue("No alarms should be present", am.getAlarms().isEmpty());
Map<Alarm.SeverityLevel, Long> zeroAlarms = new CountsMapBuilder().create();
assertEquals(zeroAlarms, am.getAlarmCounts());
assertEquals(zeroAlarms, am.getAlarmCounts(DEVICE_ID));
assertEquals("No alarms count should be present", zeroAlarms, am.getAlarmCounts());
assertEquals("No alarms count should be present", zeroAlarms, am.getAlarmCounts(DEVICE_ID));
am.updateAlarms(Sets.newHashSet(ALARM_B, ALARM_A), DEVICE_ID);
am.updateAlarms(DEVICE_ID, ImmutableSet.of(ALARM_B, ALARM_A));
verifyGettingSetsOfAlarms(am, 2, 2);
Map<Alarm.SeverityLevel, Long> critical2 = new CountsMapBuilder().with(CRITICAL, 2L).create();
assertEquals(critical2, am.getAlarmCounts());
assertEquals(critical2, am.getAlarmCounts(DEVICE_ID));
assertEquals("A critical should be present", critical2, am.getAlarmCounts());
assertEquals("A critical should be present", critical2, am.getAlarmCounts(DEVICE_ID));
am.updateAlarms(Sets.newHashSet(ALARM_A), DEVICE_ID);
am.updateAlarms(DEVICE_ID, ImmutableSet.of(ALARM_A));
verifyGettingSetsOfAlarms(am, 2, 1);
Map<Alarm.SeverityLevel, Long> critical1cleared1 =
new CountsMapBuilder().with(CRITICAL, 1L).with(CLEARED, 1L).create();
assertEquals(critical1cleared1, am.getAlarmCounts());
assertEquals(critical1cleared1, am.getAlarmCounts(DEVICE_ID));
assertEquals("A critical should be present and cleared", critical1cleared1,
am.getAlarmCounts());
assertEquals("A critical should be present and cleared", critical1cleared1,
am.getAlarmCounts(DEVICE_ID));
// No change map when same alarms sent
am.updateAlarms(Sets.newHashSet(ALARM_A), DEVICE_ID);
am.updateAlarms(DEVICE_ID, ImmutableSet.of(ALARM_A));
verifyGettingSetsOfAlarms(am, 2, 1);
assertEquals(critical1cleared1, am.getAlarmCounts());
assertEquals(critical1cleared1, am.getAlarmCounts(DEVICE_ID));
assertEquals("Map should not be changed for same alarm", critical1cleared1,
am.getAlarmCounts());
assertEquals("Map should not be changed for same alarm", critical1cleared1,
am.getAlarmCounts(DEVICE_ID));
am.updateAlarms(Sets.newHashSet(ALARM_A, ALARM_A_WITHSRC), DEVICE_ID);
am.updateAlarms(DEVICE_ID, ImmutableSet.of(ALARM_A, ALARM_A_WITHSRC));
verifyGettingSetsOfAlarms(am, 3, 2);
Map<Alarm.SeverityLevel, Long> critical2cleared1 =
new CountsMapBuilder().with(CRITICAL, 2L).with(CLEARED, 1L).create();
assertEquals(critical2cleared1, am.getAlarmCounts());
assertEquals(critical2cleared1, am.getAlarmCounts(DEVICE_ID));
assertEquals("A critical should be present", critical2cleared1, am.getAlarmCounts());
assertEquals("A critical should be present", critical2cleared1, am.getAlarmCounts(DEVICE_ID));
am.updateAlarms(Sets.newHashSet(), DEVICE_ID);
am.updateAlarms(DEVICE_ID, ImmutableSet.of());
verifyGettingSetsOfAlarms(am, 3, 0);
assertEquals(new CountsMapBuilder().with(CLEARED, 3L).create(), am.getAlarmCounts(DEVICE_ID));
assertEquals("No alarms for unknown devices", zeroAlarms, am.getAlarmCounts(DeviceId.NONE));
assertEquals("No alarms for unknown devices", zeroAlarms, am.getAlarmCounts(DeviceId.deviceId("junk:junk")));
assertEquals("The counts should be empty for unknown devices", zeroAlarms,
am.getAlarmCounts(DeviceId.NONE));
assertEquals("The counts should be empty for unknown devices", zeroAlarms,
am.getAlarmCounts(DeviceId.deviceId("junk:junk")));
}
private void verifyGettingSetsOfAlarms(AlarmsManager am, int expectedTotal, int expectedActive) {
assertEquals("Wrong total", expectedTotal, am.getAlarms().size());
assertEquals("Wrong active count", expectedActive, am.getActiveAlarms().size());
assertEquals("Incorrect total alarms", expectedTotal, am.getAlarms().size());
assertEquals("Incorrect active alarms count", expectedActive, am.getActiveAlarms().size());
}
private static final DeviceId DEVICE_ID = DeviceId.deviceId("foo:bar");
private static final DefaultAlarm ALARM_A = new DefaultAlarm.Builder(
DEVICE_ID, "aaa", Alarm.SeverityLevel.CRITICAL, 0).build();
private static final DefaultAlarm ALARM_A_WITHSRC = new DefaultAlarm.Builder(
ALARM_A).forSource(AlarmEntityId.alarmEntityId("port:foo")).build();
private static final DefaultAlarm ALARM_B = new DefaultAlarm.Builder(
DEVICE_ID, "bbb", Alarm.SeverityLevel.CRITICAL, 0).build();
private static class CountsMapBuilder {
......
......@@ -46,7 +46,7 @@ import static org.slf4j.LoggerFactory.getLogger;
@Path("alarms")
public class AlarmsWebResource extends AbstractWebResource {
public static final String ALARM_NOT_FOUND = "Alarm is not found";
private static final String ALARM_NOT_FOUND = "Alarm is not found";
private final Logger log = getLogger(getClass());
......@@ -63,7 +63,7 @@ public class AlarmsWebResource extends AbstractWebResource {
@DefaultValue("") @QueryParam("devId") String devId
) {
log.info("Requesting all alarms, includeCleared={}", includeCleared);
log.debug("Requesting all alarms, includeCleared={}", includeCleared);
AlarmService service = get(AlarmService.class);
Iterable<Alarm> alarms;
......@@ -90,7 +90,7 @@ public class AlarmsWebResource extends AbstractWebResource {
@Path("{id}")
@Produces(MediaType.APPLICATION_JSON)
public Response getAlarm(@PathParam("id") String id) {
log.info("HTTP GET alarm for id={}", id);
log.debug("HTTP GET alarm for id={}", id);
AlarmId alarmId = toAlarmId(id);
Alarm alarm = get(AlarmService.class).getAlarm(alarmId);
......@@ -113,11 +113,11 @@ public class AlarmsWebResource extends AbstractWebResource {
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response update(@PathParam("alarm_id") String alarmIdPath, InputStream stream) {
log.info("PUT NEW ALARM at /{}", alarmIdPath);
log.debug("PUT NEW ALARM at /{}", alarmIdPath);
try {
ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
log.info("jsonTree={}", jsonTree);
log.debug("jsonTree={}", jsonTree);
Alarm alarm = new AlarmCodec().decode(jsonTree, this);
......@@ -139,7 +139,7 @@ public class AlarmsWebResource extends AbstractWebResource {
}
}
private static AlarmId toAlarmId(String id) {
private AlarmId toAlarmId(String id) {
try {
return AlarmId.alarmId(Long.parseLong(id));
} catch (NumberFormatException ex) {
......
......@@ -6,6 +6,7 @@ CURRENT_TARGET = ':' + CURRENT_NAME
COMPILE_DEPS = [
'//lib:CORE_DEPS',
'//protocols/snmp/api:onos-snmp-api',
'//incubator/api:onos-incubator-api',
'//lib:org.apache.servicemix.bundles.snmp4j',
'//lib:snmp-core',
'//lib:bti7000',
......
......@@ -13,7 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.provider.snmp.alarm.impl;
package org.onosproject.drivers.bti;
import com.btisystems.mibbler.mibs.bti7000.bti7000_13_2_0.I_Device;
import com.btisystems.mibbler.mibs.bti7000.bti7000_13_2_0._OidRegistry;
......@@ -23,31 +24,34 @@ import com.btisystems.pronx.ems.core.model.ClassRegistry;
import com.btisystems.pronx.ems.core.model.IClassRegistry;
import com.btisystems.pronx.ems.core.model.NetworkDevice;
import com.btisystems.pronx.ems.core.snmp.ISnmpSession;
import java.io.IOException;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashSet;
import java.util.Set;
import java.util.TimeZone;
import com.google.common.collect.ImmutableList;
import org.apache.commons.lang.StringUtils;
import org.onosproject.incubator.net.faultmanagement.alarm.Alarm;
import org.onosproject.incubator.net.faultmanagement.alarm.AlarmConsumer;
import org.onosproject.incubator.net.faultmanagement.alarm.AlarmEntityId;
import org.onosproject.incubator.net.faultmanagement.alarm.DefaultAlarm;
import org.onosproject.net.DeviceId;
import org.onosproject.net.driver.AbstractHandlerBehaviour;
import org.onosproject.snmp.SnmpController;
import org.slf4j.Logger;
import static org.slf4j.LoggerFactory.getLogger;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.OctetString;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.TimeZone;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.slf4j.LoggerFactory.getLogger;
/**
* BTI 7000 specific implementation to provide a list of current alarms.
* @deprecated 1.5.0 Falcon, not compliant with ONOS SB and driver architecture.
*/
@Deprecated
public class Bti7000SnmpAlarmProvider implements SnmpDeviceAlarmProvider {
public class Bti7000SnmpAlarmConsumer extends AbstractHandlerBehaviour implements AlarmConsumer {
private final Logger log = getLogger(getClass());
protected static final IClassRegistry CLASS_REGISTRY = new ClassRegistry(_OidRegistry.oidRegistry, I_Device.class);
......@@ -55,40 +59,6 @@ public class Bti7000SnmpAlarmProvider implements SnmpDeviceAlarmProvider {
static final int ALARM_SEVERITY_MAJOR = 3;
static final int ALARM_SEVERITY_CRITICAL = 4;
@Override
public Collection<Alarm> getAlarms(ISnmpSession session, DeviceId deviceID) {
log.info("Getting alarms for BTI 7000 device at {}", deviceID);
Set<Alarm> alarms = new HashSet<>();
NetworkDevice networkDevice = new NetworkDevice(CLASS_REGISTRY,
session.getAddress().getHostAddress());
try {
session.walkDevice(networkDevice, Arrays.asList(
new OID[]{CLASS_REGISTRY.getClassToOidMap().get(ActAlarmTable.class)}));
IActAlarmTable deviceAlarms = (IActAlarmTable) networkDevice.getRootObject()
.getEntity(CLASS_REGISTRY.getClassToOidMap().get(ActAlarmTable.class));
if ((deviceAlarms != null) && (deviceAlarms.getActAlarmEntry() != null)
&& (!deviceAlarms.getActAlarmEntry().isEmpty())) {
deviceAlarms.getActAlarmEntry().values().stream().forEach((alarm) -> {
DefaultAlarm.Builder alarmBuilder = new DefaultAlarm.Builder(
deviceID, alarm.getActAlarmDescription(),
mapAlarmSeverity(alarm.getActAlarmSeverity()),
getLocalDateAndTime(alarm.getActAlarmDateAndTime(), null, null).getTime())
.forSource(AlarmEntityId.alarmEntityId("other:" + alarm.getActAlarmInstanceIdx()));
alarms.add(alarmBuilder.build());
});
}
log.info("Conditions retrieved: {}", deviceAlarms);
} catch (IOException ex) {
log.error("Error reading alarms for device {}.", deviceID, ex);
}
return alarms;
}
private Alarm.SeverityLevel mapAlarmSeverity(int intAlarmSeverity) {
Alarm.SeverityLevel mappedSeverity;
......@@ -108,18 +78,19 @@ public class Bti7000SnmpAlarmProvider implements SnmpDeviceAlarmProvider {
}
return mappedSeverity;
}
/**
* Converts an SNMP string representation into a {@link Date} object,
* and applies time zone conversion to provide the time on the local machine, ie PSM server.
*
* @param actAlarmDateAndTime MIB-II DateAndTime formatted. May optionally contain
* a timezone offset in 3 extra bytes
* @param sysInfoTimeZone Must be supplied if actAlarmDateAndTime is just local time (with no timezone)
* @param swVersion Must be supplied if actAlarmDateAndTime is just local time (with no timezone)
* a timezone offset in 3 extra bytes
* @param sysInfoTimeZone Must be supplied if actAlarmDateAndTime is just local time (with no timezone)
* @param swVersion Must be supplied if actAlarmDateAndTime is just local time (with no timezone)
* @return adjusted {@link Date} or a simple conversion if other fields are null.
*/
public static Date getLocalDateAndTime(String actAlarmDateAndTime, String sysInfoTimeZone,
String swVersion) {
String swVersion) {
if (StringUtils.isBlank(actAlarmDateAndTime)) {
return null;
}
......@@ -141,14 +112,13 @@ public class Bti7000SnmpAlarmProvider implements SnmpDeviceAlarmProvider {
/**
* This method is similar to SNMP4J approach with some fixes for the 11-bytes version (ie the one with timezone
* offset).
*
* <p>
* For original makeCalendar refer @see http://www.snmp4j.org/agent/doc/org/snmp4j/agent/mo/snmp/DateAndTime.html
*
* <p>
* Creates a <code>GregorianCalendar</code> from a properly formatted SNMP4J DateAndTime <code>OctetString</code>.
*
* @param dateAndTimeValue an OctetString conforming to the DateAndTime TC.
* @return the corresponding <code>GregorianCalendar</code> instance.
*
*/
public static GregorianCalendar btiMakeCalendar(OctetString dateAndTimeValue) {
int year = (dateAndTimeValue.get(0) & 0xFF) * 256
......@@ -179,4 +149,44 @@ public class Bti7000SnmpAlarmProvider implements SnmpDeviceAlarmProvider {
private static TimeZone getTimeZone() {
return Calendar.getInstance().getTimeZone();
}
@Override
public List<Alarm> consumeAlarms() {
SnmpController controller = checkNotNull(handler().get(SnmpController.class));
ISnmpSession session;
List<Alarm> alarms = new ArrayList<>();
DeviceId deviceId = handler().data().deviceId();
try {
session = controller.getSession(deviceId);
log.debug("Getting alarms for BTI 7000 device at {}", deviceId);
NetworkDevice networkDevice = new NetworkDevice(CLASS_REGISTRY,
session.getAddress().getHostAddress());
session.walkDevice(networkDevice, Collections.singletonList(
CLASS_REGISTRY.getClassToOidMap().get(ActAlarmTable.class)));
IActAlarmTable deviceAlarms = (IActAlarmTable) networkDevice.getRootObject()
.getEntity(CLASS_REGISTRY.getClassToOidMap().get(ActAlarmTable.class));
if ((deviceAlarms != null) && (deviceAlarms.getActAlarmEntry() != null)
&& (!deviceAlarms.getActAlarmEntry().isEmpty())) {
deviceAlarms.getActAlarmEntry().values().stream().forEach((alarm) -> {
DefaultAlarm.Builder alarmBuilder = new DefaultAlarm.Builder(
deviceId, alarm.getActAlarmDescription(),
mapAlarmSeverity(alarm.getActAlarmSeverity()),
getLocalDateAndTime(alarm.getActAlarmDateAndTime(), null, null).getTime())
.forSource(AlarmEntityId.alarmEntityId("other:" + alarm.getActAlarmInstanceIdx()));
alarms.add(alarmBuilder.build());
});
}
log.debug("Conditions retrieved: {}", deviceAlarms);
} catch (IOException ex) {
log.error("Error reading alarms for device {}.", deviceId, ex);
alarms.add(controller.buildWalkFailedAlarm(deviceId));
}
return ImmutableList.copyOf(alarms);
}
}
......
/*
* Copyright 2016 Open Networking Laboratory
*
* 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.drivers.bti;
import com.btisystems.mibbler.mibs.netsnmp.netsnmp.I_Device;
import com.btisystems.mibbler.mibs.netsnmp.netsnmp._OidRegistry;
import com.btisystems.mibbler.mibs.netsnmp.netsnmp.mib_2.interfaces.IfTable;
import com.btisystems.pronx.ems.core.model.ClassRegistry;
import com.btisystems.pronx.ems.core.model.IClassRegistry;
import com.btisystems.pronx.ems.core.model.NetworkDevice;
import com.btisystems.pronx.ems.core.snmp.ISnmpSession;
import com.google.common.collect.ImmutableList;
import org.onosproject.incubator.net.faultmanagement.alarm.Alarm;
import org.onosproject.incubator.net.faultmanagement.alarm.AlarmConsumer;
import org.onosproject.incubator.net.faultmanagement.alarm.AlarmEntityId;
import org.onosproject.incubator.net.faultmanagement.alarm.DefaultAlarm;
import org.onosproject.net.DeviceId;
import org.onosproject.net.driver.AbstractHandlerBehaviour;
import org.onosproject.snmp.SnmpController;
import org.slf4j.Logger;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.slf4j.LoggerFactory.getLogger;
/**
* Net SNMP specific implementation to provide a list of current alarms.
*/
public class NetSnmpAlarmConsumer extends AbstractHandlerBehaviour implements AlarmConsumer {
private final Logger log = getLogger(getClass());
protected static final IClassRegistry CLASS_REGISTRY =
new ClassRegistry(_OidRegistry.oidRegistry, I_Device.class);
@Override
public List<Alarm> consumeAlarms() {
SnmpController controller = checkNotNull(handler().get(SnmpController.class));
List<Alarm> alarms = new ArrayList<>();
ISnmpSession session;
DeviceId deviceId = handler().data().deviceId();
try {
session = controller.getSession(deviceId);
NetworkDevice networkDevice = new NetworkDevice(CLASS_REGISTRY,
session.getAddress()
.getHostAddress());
session.walkDevice(networkDevice, Collections.singletonList(
CLASS_REGISTRY.getClassToOidMap().get(IfTable.class)));
IfTable interfaceTable = (IfTable) networkDevice.getRootObject()
.getEntity(CLASS_REGISTRY.getClassToOidMap().get(IfTable.class));
if (interfaceTable != null) {
interfaceTable.getEntries().values().stream().forEach((ifEntry) -> {
if (ifEntry.getIfAdminStatus() == 1 && ifEntry.getIfOperStatus() == 2) {
alarms.add(new DefaultAlarm.Builder(deviceId, "Link Down.",
Alarm.SeverityLevel.CRITICAL,
System.currentTimeMillis())
.forSource(AlarmEntityId
.alarmEntityId("port:" + ifEntry.
getIfDescr())).build());
}
log.debug("Interface: " + ifEntry);
});
}
} catch (IOException ex) {
log.error("Error reading alarms for device {}.", deviceId, ex);
alarms.add(controller.buildWalkFailedAlarm(deviceId));
}
return ImmutableList.copyOf(alarms);
}
}
......@@ -19,10 +19,14 @@
<driver name="bti7000" manufacturer="bti" hwVersion="1.0.0" swVersion="1.0.0">
<behaviour api="org.onosproject.net.device.DeviceDescriptionDiscovery"
impl="org.onosproject.drivers.bti.Bti7000DeviceDescriptor"/>
<behaviour api="org.onosproject.incubator.net.faultmanagement.alarm.AlarmConsumer"
impl="org.onosproject.drivers.bti.Bti7000SnmpAlarmConsumer"/>
</driver>
<driver name="NetSnmp" manufacturer="bti" hwVersion="1.0.0" swVersion="1.0.0">
<behaviour api="org.onosproject.net.device.DeviceDescriptionDiscovery"
impl="org.onosproject.drivers.bti.NetSnmpDeviceDescriptor"/>
<behaviour api="org.onosproject.incubator.net.faultmanagement.alarm.AlarmConsumer"
impl="org.onosproject.drivers.bti.NetSnmpAlarmConsumer"/>
</driver>
</drivers>
......
/*
* Copyright 2016 Open Networking Laboratory
*
* 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.incubator.net.faultmanagement.alarm;
import org.onosproject.net.driver.HandlerBehaviour;
import java.util.List;
/**
* Abstraction of a device behaviour capable of retrieving/consuming list of
* pending alarms from the device.
*/
public interface AlarmConsumer extends HandlerBehaviour {
/**
* Returns the list of active alarms consumed from the device.
* This means that subsequent retrieval of alarms will not contain
* any duplicates.
*
* @return list of alarms consumed from the device
*/
List<Alarm> consumeAlarms();
}
......@@ -19,30 +19,18 @@ import org.onosproject.net.DeviceId;
import org.onosproject.net.provider.Provider;
/**
* Abstraction of a Alarm provider.
* Abstraction of an entity capable of supplying alarms collected from
* network devices.
*/
public interface AlarmProvider extends Provider {
/**
* Triggers an asynchronous discovery of the alarms on the specified device, intended to refresh internal alarm
* model for the device. An indirect result of this should be a event sent later with discovery result ie a set of
* alarms.
* Triggers an asynchronous discovery of the alarms on the specified device,
* intended to refresh internal alarm model for the device. An indirect
* result of this should be a event sent later with discovery result
* ie a set of alarms.
*
* @param deviceId ID of device to be probed
*/
void triggerProbe(DeviceId deviceId);
/**
* Register a listener for alarms.
*
* @param listener the listener to notify
*/
void addAlarmListener(AlarmListener listener);
/**
* Unregister a listener.
*
* @param listener the listener to unregister
*/
void removeAlarmListener(AlarmListener listener);
}
......
/*
<<<<<<< HEAD
* Copyright 2015-present Open Networking Laboratory
=======
* Copyright 2015-present Open Networking Laboratory
>>>>>>> master
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -18,7 +14,29 @@
* limitations under the License.
*/
package org.onosproject.incubator.net.faultmanagement.alarm;
import org.onosproject.net.provider.ProviderId;
import java.util.Set;
/**
* Provider that will support SNMP alarm discoveries.
* Adapter for Alarm Provider Registry.
*/
package org.onosproject.provider.snmp.alarm.impl;
public class AlarmProviderRegistryAdapter implements AlarmProviderRegistry {
@Override
public AlarmProviderService register(AlarmProvider provider) {
return null;
}
@Override
public void unregister(AlarmProvider provider) {
}
@Override
public Set<ProviderId> getProviders() {
return null;
}
}
......
......@@ -55,7 +55,6 @@
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.scr</artifactId>
<version>1.8.2</version>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
......@@ -71,5 +70,4 @@
</plugin>
</plugins>
</build>
</project>
......
......@@ -14,6 +14,9 @@ TEST_DEPS = [
'//core/common:onos-core-common-tests',
'//incubator/store:onos-incubator-store',
'//core/store/serializers:onos-core-serializers',
'//utils/osgi:onlab-osgi',
'//utils/osgi:onlab-osgi-tests',
'//incubator/api:onos-incubator-api-tests',
]
osgi_jar(
......
......@@ -41,6 +41,15 @@
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-incubator-api</artifactId>
<version>${project.version}</version>
<classifier>tests</classifier>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-core-common</artifactId>
<version>${project.version}</version>
<classifier>tests</classifier>
......@@ -67,11 +76,6 @@
</dependency>
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.scr.annotations</artifactId>
</dependency>
<dependency>
<groupId>org.apache.karaf.features</groupId>
<artifactId>org.apache.karaf.features.core</artifactId>
</dependency>
......@@ -87,6 +91,19 @@
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.scr.annotations</artifactId>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onlab-osgi</artifactId>
<version>${project.version}</version>
<classifier>tests</classifier>
<scope>test</scope>
</dependency>
</dependencies>
<build>
......
/*
* Copyright 2016 Open Networking Laboratory
*
* 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.incubator.net.faultmanagement.alarm.impl;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Modified;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onosproject.incubator.net.faultmanagement.alarm.AlarmConsumer;
import org.onosproject.incubator.net.faultmanagement.alarm.AlarmProvider;
import org.onosproject.incubator.net.faultmanagement.alarm.AlarmProviderRegistry;
import org.onosproject.incubator.net.faultmanagement.alarm.AlarmProviderService;
import org.onosproject.mastership.MastershipEvent;
import org.onosproject.mastership.MastershipListener;
import org.onosproject.mastership.MastershipService;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.device.DeviceEvent;
import org.onosproject.net.device.DeviceListener;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.provider.AbstractProvider;
import org.onosproject.net.provider.ProviderId;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import java.util.Dictionary;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import static com.google.common.base.Strings.isNullOrEmpty;
import static org.onlab.util.Tools.get;
import static org.onlab.util.Tools.groupedThreads;
import static org.slf4j.LoggerFactory.getLogger;
/**
* Alarm provider capable of polling the environment using the device driver
* {@link AlarmConsumer} behaviour.
*/
@Component(immediate = true)
public class PollingAlarmProvider extends AbstractProvider implements AlarmProvider {
private final Logger log = getLogger(getClass());
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected DeviceService deviceService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected MastershipService mastershipService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected AlarmProviderRegistry providerRegistry;
protected AlarmProviderService providerService;
protected ScheduledExecutorService alarmsExecutor;
private ScheduledFuture<?> scheduledTask;
private ExecutorService eventHandlingExecutor;
protected final MastershipListener mastershipListener = new InternalMastershipListener();
protected final DeviceListener deviceListener = new InternalDeviceListener();
private static final int CORE_POOL_SIZE = 10;
private static final int DEFAULT_POLL_FREQUENCY_SECONDS = 60;
@Property(name = "alarmPollFrequencySeconds", intValue = DEFAULT_POLL_FREQUENCY_SECONDS,
label = "Frequency (in seconds) for polling alarm from devices")
protected int alarmPollFrequencySeconds = DEFAULT_POLL_FREQUENCY_SECONDS;
// TODO implement purging of old alarms.
private static final int DEFAULT_CLEAR_FREQUENCY_SECONDS = 500;
@Property(name = "clearedAlarmPurgeSeconds", intValue = DEFAULT_CLEAR_FREQUENCY_SECONDS,
label = "Frequency (in seconds) for deleting cleared alarms")
private int clearedAlarmPurgeFrequencySeconds = DEFAULT_CLEAR_FREQUENCY_SECONDS;
public PollingAlarmProvider() {
super(new ProviderId("default", "org.onosproject.core"));
}
@Activate
public void activate(ComponentContext context) {
alarmsExecutor = Executors.newScheduledThreadPool(CORE_POOL_SIZE);
eventHandlingExecutor =
Executors.newFixedThreadPool(CORE_POOL_SIZE,
groupedThreads("onos/pollingalarmprovider",
"device-installer-%d", log));
providerService = providerRegistry.register(this);
deviceService.addListener(deviceListener);
mastershipService.addListener(mastershipListener);
if (context == null) {
alarmPollFrequencySeconds = DEFAULT_POLL_FREQUENCY_SECONDS;
log.info("No component configuration");
} else {
Dictionary<?, ?> properties = context.getProperties();
alarmPollFrequencySeconds = getNewPollFrequency(properties, alarmPollFrequencySeconds);
}
scheduledTask = schedulePolling();
log.info("Started");
}
@Deactivate
public void deactivate() {
providerRegistry.unregister(this);
mastershipService.removeListener(mastershipListener);
deviceService.removeListener(deviceListener);
alarmsExecutor.shutdown();
providerService = null;
log.info("Stopped");
}
@Modified
public void modified(ComponentContext context) {
if (context == null) {
log.info("No component configuration");
return;
}
Dictionary<?, ?> properties = context.getProperties();
int newPollFrequency = getNewPollFrequency(properties, alarmPollFrequencySeconds);
if (newPollFrequency != alarmPollFrequencySeconds) {
alarmPollFrequencySeconds = newPollFrequency;
//stops the old scheduled task
scheduledTask.cancel(true);
//schedules new task at the new polling rate
scheduledTask = schedulePolling();
}
}
private ScheduledFuture schedulePolling() {
return alarmsExecutor.scheduleAtFixedRate(this::consumeAlarms,
alarmPollFrequencySeconds / 4, alarmPollFrequencySeconds,
TimeUnit.SECONDS);
}
private int getNewPollFrequency(Dictionary<?, ?> properties, int pollFrequency) {
int newPollFrequency;
try {
String s = get(properties, "pollFrequency");
newPollFrequency = isNullOrEmpty(s) ? pollFrequency : Integer.parseInt(s.trim());
} catch (NumberFormatException | ClassCastException e) {
newPollFrequency = DEFAULT_POLL_FREQUENCY_SECONDS;
}
return newPollFrequency;
}
@Override
public void triggerProbe(DeviceId deviceId) {
if (mastershipService.isLocalMaster(deviceId)) {
triggerProbe(deviceService.getDevice(deviceId));
}
}
private void triggerProbe(Device device) {
alarmsExecutor.submit(() -> consumeAlarms(device));
}
private void consumeAlarms() {
deviceService.getAvailableDevices().forEach(device -> {
if (mastershipService.isLocalMaster(device.id())) {
consumeAlarms(device);
}
});
}
private void consumeAlarms(Device device) {
if (device.is(AlarmConsumer.class)) {
providerService.updateAlarmList(device.id(),
device.as(AlarmConsumer.class).consumeAlarms());
} else {
log.info("Device {} does not support alarm consumer behaviour", device.id());
}
}
private class InternalMastershipListener implements MastershipListener {
@Override
public boolean isRelevant(MastershipEvent event) {
return mastershipService.isLocalMaster(event.subject());
}
@Override
public void event(MastershipEvent event) {
triggerProbe(event.subject());
}
}
/**
* Internal listener for device service events.
*/
private class InternalDeviceListener implements DeviceListener {
@Override
public boolean isRelevant(DeviceEvent event) {
return event.type().equals(DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED)
&& deviceService.isAvailable(event.subject().id());
}
@Override
public void event(DeviceEvent event) {
log.debug("InternalDeviceListener has got event from device-service{} with ", event);
eventHandlingExecutor.execute(() -> triggerProbe(event.subject().id()));
}
}
}
......@@ -13,13 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.incubator.net.faultmanagement.alarm;
import org.onosproject.event.EventListener;
/**
* Entity capable of receiving Alarm related events.
* Abstractions for interacting with alarms. An alarm is a persistent indication
* of a fault that clears only when the triggering condition has been resolved.
*/
public interface AlarmListener extends EventListener<AlarmEvent> {
}
package org.onosproject.incubator.net.faultmanagement.alarm.impl;
......
......@@ -77,7 +77,6 @@
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.onosproject</groupId>
<artifactId>onos-maven-plugin</artifactId>
......
......@@ -83,7 +83,6 @@
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
......@@ -92,5 +91,4 @@
</plugin>
</plugins>
</build>
</project>
......
SRC = 'src/main/java/org/onosproject/**/'
TEST = 'src/test/java/org/onosproject/**/'
CURRENT_NAME = 'onos-snmp-provider-alarm'
CURRENT_TARGET = ':' + CURRENT_NAME
COMPILE_DEPS = [
'//lib:CORE_DEPS',
'//lib:org.apache.servicemix.bundles.snmp4j',
'//lib:snmp-core',
'//lib:bti7000',
'//lib:mibs-net-snmp',
'//lib:mibs-rfc',
'//incubator/api:onos-incubator-api',
'//protocols/snmp/api:onos-snmp-api',
]
TEST_DEPS = [
'//lib:TEST',
]
osgi_jar(
name = CURRENT_NAME,
srcs = glob([SRC + '/*.java']),
deps = COMPILE_DEPS,
visibility = ['PUBLIC'],
)
java_test(
name = 'tests',
srcs = glob([TEST + '/*.java']),
deps = COMPILE_DEPS +
TEST_DEPS +
[CURRENT_TARGET],
source_under_test = [CURRENT_TARGET],
)
......@@ -20,7 +20,6 @@
features="${project.artifactId}">
<description>${project.description}</description>
<artifact>mvn:${project.groupId}/onos-snmp-provider-device/${project.version}</artifact>
<artifact>mvn:${project.groupId}/onos-snmp-provider-alarm/${project.version}</artifact>
<artifact>mvn:${project.groupId}/onos-snmp-api/${project.version}</artifact>
<artifact>mvn:${project.groupId}/onos-snmp-ctl/${project.version}</artifact>
......
......@@ -22,7 +22,6 @@
<bundle>mvn:${project.groupId}/onos-snmp-api/${project.version}</bundle>
<bundle>mvn:${project.groupId}/onos-snmp-ctl/${project.version}</bundle>
<bundle>mvn:${project.groupId}/onos-snmp-provider-device/${project.version}</bundle>
<bundle>mvn:${project.groupId}/onos-snmp-provider-alarm/${project.version}</bundle>
<bundle>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.snmp4j/2.3.4_1</bundle>
<bundle>mvn:com.btisystems/snmp-core/1.3-SNAPSHOT</bundle>
......
......@@ -37,11 +37,6 @@
<artifactId>onos-snmp-provider-device</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-snmp-provider-alarm</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>
......
......@@ -77,12 +77,12 @@
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-core-net</artifactId>
<version>1.6.0-SNAPSHOT</version>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
<artifactId>onos-api</artifactId>
<version>1.6.0-SNAPSHOT</version>
<version>${project.version}</version>
<classifier>tests</classifier>
<scope>test</scope>
</dependency>
......@@ -96,4 +96,3 @@
</plugins>
</build>
</project>
......
......@@ -48,7 +48,6 @@ import org.onosproject.net.device.DeviceService;
import org.onosproject.net.device.DeviceServiceAdapter;
import org.onosproject.net.device.DeviceStore;
import org.onosproject.net.device.DeviceStoreAdapter;
import org.onosproject.net.driver.DriverService;
import org.onosproject.net.driver.DriverServiceAdapter;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.snmp.SnmpController;
......
......@@ -34,7 +34,6 @@
<modules>
<module>device</module>
<module>app</module>
<module>alarm</module>
</modules>
<repositories>
......