AlarmConsumer for CienaWaveServer REST driver
Change-Id: Ibdf03871173fe5ef95eb9ac96570e66e1b066fa3
diff --git a/drivers/ciena/src/main/java/org/onosproject/drivers/ciena/CienaRestDevice.java b/drivers/ciena/src/main/java/org/onosproject/drivers/ciena/CienaRestDevice.java
index 5d8c0c5..17fce90 100644
--- a/drivers/ciena/src/main/java/org/onosproject/drivers/ciena/CienaRestDevice.java
+++ b/drivers/ciena/src/main/java/org/onosproject/drivers/ciena/CienaRestDevice.java
@@ -17,6 +17,10 @@
import org.onlab.util.Frequency;
import org.onosproject.driver.optical.flowrule.CrossConnectCache;
+import org.onosproject.incubator.net.faultmanagement.alarm.Alarm;
+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.ChannelSpacing;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Port;
@@ -38,6 +42,10 @@
import org.onosproject.protocol.rest.RestSBController;
import org.slf4j.Logger;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeParseException;
import java.util.Objects;
import java.util.List;
import java.util.Collection;
@@ -51,6 +59,8 @@
import javax.ws.rs.core.Response;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+
import org.apache.commons.lang3.tuple.Pair;
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -61,12 +71,7 @@
import static org.slf4j.LoggerFactory.getLogger;
public class CienaRestDevice {
- private DeviceId deviceId;
- private RestSBController controller;
- private CrossConnectCache crossConnectCache;
- private DeviceService deviceService;
-
- private final Logger log = getLogger(getClass());
+ private static final Frequency BASE_FREQUENCY = Frequency.ofGHz(193_950);
private static final String ENABLED = "enabled";
private static final String DISABLED = "disabled";
private static final String VALUE = "value";
@@ -74,10 +79,23 @@
private static final String ADMIN_STATE = "admin-state";
private static final String WAVELENGTH = "wavelength";
private static final String DATA = "data";
+ private static final String ACTIVE = "active";
+ private static final String ACKNOWLEDGE = "acknowledged";
+ private static final String SEVERITY = "severity";
+ private static final String DESCRIPTION = "description";
+ private static final String INSTANCE = "instance";
+ private static final String PORT = "port";
+ private static final String PTP = "ptp";
+ private static final String UTC = "UTC";
+ private static final String OTHER = "other";
+ private static final String DATE_TIME_FORMAT = "EEE MMM [ ]d HH:mm:ss yyyy";
+ //keys
+ private static final String ALARM_KEY = "ws-alarms";
+ private static final String ALARM_INSTANCE_ID = "alarm-instance-id";
+ private static final String ALARM_TABLE_ID = "alarm-table-id";
+ private static final String ALARM_LOCAL_DATE_TIME = "local-date-time";
private static final String LINE_SYSTEM_CHANNEL_NUMBER = "ciena-ws-ptp-modem:line-system-channel-number";
private static final String FREQUENCY_KEY = "ciena-ws-ptp-modem:frequency";
- private static final Frequency BASE_FREQUENCY = Frequency.ofGHz(193_950);
-
//URIs
private static final String PORT_URI = "ws-ptps/ptps/%s";
private static final String TRANSMITTER_URI = PORT_URI + "/properties/transmitter";
@@ -85,9 +103,17 @@
private static final String WAVELENGTH_URI = TRANSMITTER_URI + "/" + WAVELENGTH;
private static final String FREQUENCY_URI = TRANSMITTER_URI + "/" + FREQUENCY_KEY;
private static final String CHANNEL_URI = TRANSMITTER_URI + "/" + LINE_SYSTEM_CHANNEL_NUMBER;
-
+ private static final String ACTIVE_ALARMS_URL = ALARM_KEY + "/" + ACTIVE;
private static final List<String> LINESIDE_PORT_ID = ImmutableList.of("4", "48");
+ private final Logger log = getLogger(getClass());
+
+ private DeviceId deviceId;
+ private RestSBController controller;
+ private CrossConnectCache crossConnectCache;
+ private DeviceService deviceService;
+
+
public CienaRestDevice(DriverHandler handler) throws NullPointerException {
deviceId = handler.data().deviceId();
controller = checkNotNull(handler.get(RestSBController.class));
@@ -231,6 +257,71 @@
}
+ private AlarmEntityId getAlarmSource(String instance) {
+ AlarmEntityId source;
+ if (instance.contains(PORT)) {
+ source = AlarmEntityId.alarmEntityId(instance.replace("-", ":"));
+ } else if (instance.contains(PTP)) {
+ source = AlarmEntityId.alarmEntityId(instance.replace(PTP + "-", PORT + ":"));
+ } else {
+ source = AlarmEntityId.alarmEntityId(OTHER + ":" + instance);
+ }
+ return source;
+ }
+
+ private long parseAlarmTime(String time) {
+ /*
+ * expecting WaveServer time to be set to UTC.
+ */
+ try {
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATE_TIME_FORMAT);
+ LocalDateTime localDateTime = LocalDateTime.parse(time, formatter);
+ return localDateTime.atZone(ZoneId.of(UTC)).toInstant().toEpochMilli();
+ } catch (DateTimeParseException e2) {
+ log.error("unable to parse time {}, using system time", time);
+ return System.currentTimeMillis();
+ }
+ }
+
+ private Alarm newAlarmFromJsonNode(JsonNode jsonNode) {
+ try {
+ AlarmId alarmId = AlarmId.alarmId(checkNotNull(jsonNode.get(ALARM_INSTANCE_ID)).asText());
+ String time = checkNotNull(jsonNode.get(ALARM_LOCAL_DATE_TIME)).asText();
+ String instance = checkNotNull(jsonNode.get(INSTANCE).asText()).toLowerCase();
+ String description = checkNotNull(jsonNode.get(DESCRIPTION)).asText() + " - " + instance + " - " + time;
+ AlarmEntityId source = getAlarmSource(instance);
+ Alarm.SeverityLevel severity = Alarm.SeverityLevel.valueOf(checkNotNull(
+ jsonNode.get(SEVERITY)).asText().toUpperCase());
+
+ long timeRaised = parseAlarmTime(time);
+ boolean isAcknowledged = checkNotNull(jsonNode.get(ACKNOWLEDGE)).asBoolean();
+
+ return new DefaultAlarm.Builder(alarmId, deviceId, description, severity, timeRaised)
+ .withAcknowledged(isAcknowledged)
+ .forSource(source)
+ .build();
+
+ } catch (NullPointerException e) {
+ log.error("got exception while parsing alarm json node {} for device {}:\n", jsonNode, deviceId, e);
+ return null;
+ }
+
+ }
+
+ private List<Alarm> getActiveAlarms() {
+ log.debug("getting active alarms for device {}", deviceId);
+ try {
+ List<JsonNode> alarms = Lists.newArrayList(get(ACTIVE_ALARMS_URL).get(ACTIVE).elements());
+ return alarms.stream()
+ .map(a -> newAlarmFromJsonNode(a))
+ .filter(a -> a != null)
+ .collect(Collectors.toList());
+ } catch (IOException e) {
+ log.error("unable to get active alarms for device {}:\n", deviceId, e);
+ return null;
+ }
+ }
+
public Collection<FlowEntry> getFlowEntries() {
List<Port> ports = deviceService.getPorts(deviceId);
//driver only handles lineSide ports
@@ -250,7 +341,7 @@
}
/*
- * both inPort and outPort will be same as WaveServer only deal with same port ppt-indexes
+ * both inPort and outPort will be same as WaveServer only deal with same port ptp-indexes
* channel and spaceMultiplier are same.
* TODO: find a way to get both inPort and outPort for future when inPort may not be equal to outPort
*/
@@ -282,6 +373,11 @@
return fr;
}
+ public List<Alarm> getAlarms() {
+ log.debug("getting alarms for device {}", deviceId);
+ return getActiveAlarms();
+ }
+
private JsonNode get(String uri) throws IOException {
InputStream response = controller.get(deviceId, uri, MediaType.valueOf(MediaType.APPLICATION_JSON));
ObjectMapper om = new ObjectMapper();
diff --git a/drivers/ciena/src/main/java/org/onosproject/drivers/ciena/CienaWaveServerAlarmConsumer.java b/drivers/ciena/src/main/java/org/onosproject/drivers/ciena/CienaWaveServerAlarmConsumer.java
new file mode 100644
index 0000000..a274622
--- /dev/null
+++ b/drivers/ciena/src/main/java/org/onosproject/drivers/ciena/CienaWaveServerAlarmConsumer.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.ciena;
+
+import org.onosproject.incubator.net.faultmanagement.alarm.Alarm;
+import org.onosproject.incubator.net.faultmanagement.alarm.AlarmConsumer;
+import org.onosproject.net.driver.AbstractHandlerBehaviour;
+import org.slf4j.Logger;
+
+import java.util.List;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Ciena Wave Server Alarm Consumer.
+ */
+public class CienaWaveServerAlarmConsumer extends AbstractHandlerBehaviour implements AlarmConsumer {
+ CienaRestDevice restCiena;
+
+ private final Logger log = getLogger(getClass());
+
+ @Override
+ public List<Alarm> consumeAlarms() {
+ try {
+ restCiena = new CienaRestDevice(handler());
+ } catch (NullPointerException e) {
+ log.error("unable to create CienaRestDevice:\n", e);
+ return null;
+ }
+ return restCiena.getAlarms();
+ }
+}
diff --git a/drivers/ciena/src/main/resources/ciena-drivers.xml b/drivers/ciena/src/main/resources/ciena-drivers.xml
index 02f7a97..378626b 100644
--- a/drivers/ciena/src/main/resources/ciena-drivers.xml
+++ b/drivers/ciena/src/main/resources/ciena-drivers.xml
@@ -27,6 +27,8 @@
impl="org.onosproject.drivers.ciena.CienaFlowRuleProgrammable"/>
<behaviour api="org.onosproject.net.behaviour.LambdaQuery"
impl="org.onosproject.drivers.ciena.CienaWaveServerLambdaQuery"/>
+ <behaviour api="org.onosproject.incubator.net.faultmanagement.alarm.AlarmConsumer"
+ impl="org.onosproject.drivers.ciena.CienaWaveServerAlarmConsumer"/>
</driver>
</drivers>