Enabling alarms gathering on Nokia's Transponder
Change-Id: Id1f5a609ed28703624eaf7a70f6183183de69636
diff --git a/drivers/odtn-driver/BUILD b/drivers/odtn-driver/BUILD
index 5c65159..be11910 100644
--- a/drivers/odtn-driver/BUILD
+++ b/drivers/odtn-driver/BUILD
@@ -9,6 +9,8 @@
"//apps/odtn/api:onos-apps-odtn-api",
"//apps/optical-model:onos-apps-optical-model",
"//drivers/optical:onos-drivers-optical",
+ "//apps/faultmanagement/fmcli:onos-apps-faultmanagement-fmcli", # Enabling Alarm stuff
+ "//apps/faultmanagement/fmmgr:onos-apps-faultmanagement-fmmgr-native",
]
TEST_DEPS = TEST_ADAPTERS + [
diff --git a/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/NokiaOpenConfigAlarmConfig.java b/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/NokiaOpenConfigAlarmConfig.java
new file mode 100644
index 0000000..39d7f9c
--- /dev/null
+++ b/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/NokiaOpenConfigAlarmConfig.java
@@ -0,0 +1,263 @@
+/*
+ * Copyright 2019-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.
+ *
+ *
+ * This work was done in Nokia Bell Labs Paris
+ *
+ */
+
+package org.onosproject.drivers.odtn;
+
+import org.onlab.osgi.DefaultServiceDirectory;
+import org.onlab.packet.IpAddress;
+import org.onosproject.alarm.Alarm;
+import org.onosproject.alarm.AlarmId;
+import org.onosproject.alarm.AlarmService;
+import org.onosproject.alarm.DefaultAlarm;
+import org.onosproject.alarm.DeviceAlarmConfig;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.driver.AbstractHandlerBehaviour;
+import org.onosproject.netconf.NetconfDeviceOutputEvent;
+import org.slf4j.Logger;
+import org.w3c.dom.Document;
+import org.xml.sax.InputSource;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathFactory;
+import java.io.StringReader;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import static org.onosproject.alarm.Alarm.SeverityLevel;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * OpenConfig alarm translator for Nokia devices.
+ */
+public class NokiaOpenConfigAlarmConfig
+ extends AbstractHandlerBehaviour implements DeviceAlarmConfig {
+ private final Logger log = getLogger(getClass());
+
+ private DeviceId deviceId;
+ private AlarmService alarmService = DefaultServiceDirectory.getService(AlarmService.class);
+ private static final String XML_PATH = "/system/alarms/alarm/";
+
+ @Override
+ public boolean configureDevice(IpAddress address, int port, String protocol) {
+ return false;
+ }
+
+ @Override
+ public <T> Set<Alarm> translateAlarms(List<T> unparsedAlarms) {
+
+ boolean categoryFound = false;
+ deviceId = handler().data().deviceId();
+ Set<Alarm> alarms = new HashSet<>();
+ for (T alarm : unparsedAlarms) {
+ categoryFound = false;
+ if (alarm instanceof NetconfDeviceOutputEvent) {
+ NetconfDeviceOutputEvent event = (NetconfDeviceOutputEvent) alarm;
+ if (event.type() == NetconfDeviceOutputEvent.Type.DEVICE_NOTIFICATION) {
+ String message = event.getMessagePayload();
+ if (message.contains("<update>")) {
+ categoryFound = true;
+ DefaultAlarm newAlarm = treatUpdate(message);
+ if (newAlarm != null) {
+ alarms.add(newAlarm);
+ }
+ }
+ if (message.contains("<delete>")) {
+ categoryFound = true;
+ treatDelete(message);
+ }
+ if (!categoryFound) {
+ log.debug("[translateAlarms] Appropriate category wasn't found, " +
+ "you have something else \n {} ", message);
+ }
+ }
+ }
+ }
+
+ return alarms;
+ }
+
+
+ /**
+ * Gets <update> body out of the XML notification.
+ * @param notification - XML notification obtained from the device.
+ * @return - <update> body of the notification.
+ */
+ private String getUpdateDataFromNotification(String notification) {
+
+ String data = null;
+ int begin = notification.indexOf("<update>");
+ int end = notification.indexOf("</update>");
+ if (begin != -1 && end != -1) {
+ data = notification.substring(begin + "<update>".length(), end);
+ } else {
+ data = notification;
+ }
+
+ return data;
+ }
+
+ /**
+ * Gets <delete> body out of XML notification.
+ * @param notification - XML notification obtained from the device.
+ * @return - <delete> body of the notification.
+ */
+ private String getDeleteDataFromNotification(String notification) {
+
+ String data = null;
+ int begin = notification.indexOf("<delete>");
+ int end = notification.indexOf("</delete>");
+
+ if (begin != -1 && end != -1) {
+ data = notification.substring(begin + "<delete>".length(), end);
+ } else {
+ data = notification;
+ }
+
+ return data;
+ }
+
+ /**
+ * Treats alarm in case it contains <update> tag.
+ * @param message - XML-encoded notification obtained from the device.
+ * @return - composed alarm.
+ */
+ private DefaultAlarm treatUpdate(String message) {
+
+ return buildAlarm(getUpdateDataFromNotification(message));
+ }
+
+ /**
+ * Composes an Alarm from XML string.
+ * @param message - XML string obtained form the device.
+ * @return - composed alarm as a DefaultAlarm instance.
+ */
+ private DefaultAlarm buildAlarm(String message) {
+
+ try {
+
+ InputSource src = new InputSource(new StringReader(message));
+
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ DocumentBuilder db = dbf.newDocumentBuilder();
+ Document document = db.parse(src);
+
+ XPathFactory xpathFactory = XPathFactory.newInstance();
+ XPath xpath = xpathFactory.newXPath();
+
+ String severity = null;
+ severity = xpath.evaluate(XML_PATH +
+ "state/severity", document);
+
+ // treating alarm according to the severity level
+ if ((severity != null) & (severity != "")) {
+ // Setting flag to match correct severity
+ boolean severityFound = false;
+
+ // Extracting parameters
+ try {
+ String id = xpath.evaluate(XML_PATH + "id", document);
+ String source = xpath.evaluate(XML_PATH +
+ "state/resource", document);
+ String description = xpath.evaluate(XML_PATH +
+ "state/text", document);
+ long timeStamp = Long.parseLong(xpath.evaluate(XML_PATH +
+ "state/time-created", document));
+
+ if (severity.contains("CRITICAL")) {
+
+ return (new DefaultAlarm.Builder(AlarmId.alarmId(id),
+ deviceId, description + ":" + source,
+ SeverityLevel.CRITICAL, timeStamp).
+ withServiceAffecting(true).build());
+ }
+ if (severity.contains("MAJOR")) {
+
+ return (new DefaultAlarm.Builder(AlarmId.alarmId(id),
+ deviceId, description + ":" + source,
+ SeverityLevel.MAJOR, timeStamp).
+ withServiceAffecting(true).build());
+ }
+ if (severity.contains("MINOR")) {
+
+ return (new DefaultAlarm.Builder(AlarmId.alarmId(id),
+ deviceId, description + ":" + source,
+ SeverityLevel.MINOR, timeStamp).build());
+ }
+ if (!severityFound) {
+ // treating alarm as an unknown one?
+
+ return (new DefaultAlarm.Builder(AlarmId.alarmId(id),
+ deviceId, description + ":" + source,
+ SeverityLevel.INDETERMINATE,
+ timeStamp).build());
+ }
+ } catch (Exception e) {
+ log.error("[translateAlarms] Exception was caught during the alarm processing\n {}", e);
+ }
+ }
+ } catch (Exception e) {
+ log.error("[translateAlarms] something went wrong during notification parsing \n {}", e);
+ }
+
+ return null;
+ }
+
+ /**
+ * This method searches for similar alarm inside the Alarm store of ONOS.
+ * @param message - XML String obtained from the device.
+ * @return - alarm (if was found in the store) or null.
+ */
+ private Alarm findAlarm(String message) {
+
+ Collection<Alarm> alarms = alarmService.getAlarms(deviceId);
+ Alarm alarm = buildAlarm(message);
+ if ((alarms.contains(alarm)) & (alarm != null)) {
+ log.debug("Alarm was found \n {}", alarm);
+ return alarm;
+ }
+
+ log.debug("Alarm was NOT found \n {}", alarm);
+ return null;
+ }
+
+ /**
+ * Treats message in case it contains <delete> tag.
+ * @param message - XML-encoded notification obtained from the device.
+ * @return - composed alarm.
+ */
+ private void treatDelete(String message) {
+
+ Alarm existingAlarm = findAlarm(getDeleteDataFromNotification(message));
+ if (existingAlarm != null) {
+ alarmService.updateBookkeepingFields(existingAlarm.id(), true,
+ true, null);
+ log.debug("[treatDelete] Existing alarm was updated (CLEARED)");
+ } else {
+ log.debug("[treatDelete] We found something new here \n {} \n", message);
+ }
+
+ }
+
+
+}
diff --git a/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/NokiaOpenConfigDeviceDiscovery.java b/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/NokiaOpenConfigDeviceDiscovery.java
index 2a454c5..d061a43 100644
--- a/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/NokiaOpenConfigDeviceDiscovery.java
+++ b/drivers/odtn-driver/src/main/java/org/onosproject/drivers/odtn/NokiaOpenConfigDeviceDiscovery.java
@@ -23,6 +23,7 @@
import org.apache.commons.configuration.tree.xpath.XPathExpressionEngine;
import org.onlab.packet.ChassisId;
import org.onosproject.drivers.utilities.XmlConfigParser;
+import org.onosproject.net.AnnotationKeys;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
@@ -118,6 +119,13 @@
return ImmutableList.of();
}
cfg.load(CharSource.wrap(data).openStream());
+ try {
+ ns.startSubscription();
+ log.info("Started subscription");
+ } catch (NetconfException e) {
+ log.error("NETCONF exception caught on {} when the subscription started \n {}",
+ data().deviceId(), e);
+ }
return discoverPorts(cfg);
} catch (Exception e) {
log.error("Error discovering port details on {}", data().deviceId(), e);
@@ -171,12 +179,14 @@
String[] textStr = subComponentName.split("-");
String portComponentType = textStr[0];
String portComponentIndex = textStr[textStr.length - 1];
+ String portNumber = component.getString("name");
if (portComponentType.equals(OPTICAL_CHANNEL)) {
annotations.putIfAbsent(PORT_TYPE, OdtnPortType.LINE.value());
annotations.putIfAbsent(ONOS_PORT_INDEX, portComponentIndex.toString());
annotations.putIfAbsent(CONNECTION_ID, "connection" + portComponentIndex.toString());
+ annotations.putIfAbsent(AnnotationKeys.PORT_NAME, portNumber);
OchSignal signalId = OchSignal.newDwdmSlot(ChannelSpacing.CHL_50GHZ, 1);
return OchPortHelper.ochPortDescription(
@@ -193,6 +203,7 @@
annotations.putIfAbsent(PORT_TYPE, OdtnPortType.CLIENT.value());
annotations.putIfAbsent(ONOS_PORT_INDEX, portComponentIndex.toString());
annotations.putIfAbsent(CONNECTION_ID, "connection" + portComponentIndex.toString());
+ annotations.putIfAbsent(AnnotationKeys.PORT_NAME, portNumber);
builder.withPortNumber(PortNumber.portNumber(Long.parseLong(portComponentIndex), subComponentName));
builder.type(Type.PACKET);
@@ -305,9 +316,9 @@
private String buildLoginRpc(String userName, String passwd) {
StringBuilder rpc = new StringBuilder(RPC_TAG_NETCONF_BASE);
rpc.append("<login xmlns=\"http://nokia.com/yang/nokia-security\">");
- rpc.append("<user>");
+ rpc.append("<username>");
rpc.append(userName);
- rpc.append("</user>");
+ rpc.append("</username>");
rpc.append("<password>");
rpc.append(passwd);
rpc.append("</password>");
diff --git a/drivers/odtn-driver/src/main/resources/odtn-drivers.xml b/drivers/odtn-driver/src/main/resources/odtn-drivers.xml
index 33cec52..a32317a 100644
--- a/drivers/odtn-driver/src/main/resources/odtn-drivers.xml
+++ b/drivers/odtn-driver/src/main/resources/odtn-drivers.xml
@@ -149,6 +149,8 @@
impl="org.onosproject.net.optical.DefaultOpticalDevice"/>
<behaviour api ="org.onosproject.net.behaviour.LambdaQuery"
impl="org.onosproject.drivers.odtn.openconfig.TerminalDeviceLambdaQuery"/>
+ <behaviour api="org.onosproject.alarm.DeviceAlarmConfig"
+ impl="org.onosproject.drivers.odtn.NokiaOpenConfigAlarmConfig"/>
<behaviour api="org.onosproject.net.behaviour.PowerConfig"
impl="org.onosproject.drivers.odtn.NokiaTerminalDevicePowerConfig"/>
<property name="netconfClientCapability">urn:ietf:params:netconf:base:1.0|