Translate Polatis NETCONF notifications
Change-Id: I856b90b984dead5680c2ad757473cd3fdeeacab6
diff --git a/drivers/polatis/netconf/src/main/java/org/onosproject/drivers/polatis/netconf/PolatisAlarmConfig.java b/drivers/polatis/netconf/src/main/java/org/onosproject/drivers/polatis/netconf/PolatisAlarmConfig.java
new file mode 100644
index 0000000..33cb860
--- /dev/null
+++ b/drivers/polatis/netconf/src/main/java/org/onosproject/drivers/polatis/netconf/PolatisAlarmConfig.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2018 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.polatis.netconf;
+
+import org.onlab.packet.IpAddress;
+
+import org.onosproject.incubator.net.faultmanagement.alarm.Alarm;
+import org.onosproject.incubator.net.faultmanagement.alarm.AlarmId;
+import org.onosproject.incubator.net.faultmanagement.alarm.DefaultAlarm;
+import org.onosproject.incubator.net.faultmanagement.alarm.DeviceAlarmConfig;
+import org.onosproject.incubator.net.faultmanagement.alarm.XmlEventParser;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.driver.AbstractHandlerBehaviour;
+import org.onosproject.netconf.NetconfDeviceOutputEvent;
+
+import org.slf4j.Logger;
+
+import org.xml.sax.SAXException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+import javax.xml.parsers.ParserConfigurationException;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Polatis specific implementation to provide asynchronous alarms via NETCONF.
+ */
+public class PolatisAlarmConfig extends AbstractHandlerBehaviour implements DeviceAlarmConfig {
+ private final Logger log = getLogger(getClass());
+
+ private DeviceId deviceId;
+
+ @Override
+ public boolean configureDevice(IpAddress address, int port, String protocol) {
+ return false;
+ }
+
+ @Override
+ public <T> Set<Alarm> translateAlarms(List<T> unparsedAlarms) {
+ deviceId = handler().data().deviceId();
+ Set<Alarm> alarms = new HashSet<>();
+ for (T alarm : unparsedAlarms) {
+ if (alarm instanceof NetconfDeviceOutputEvent) {
+ NetconfDeviceOutputEvent event = (NetconfDeviceOutputEvent) alarm;
+ if (event.type() == NetconfDeviceOutputEvent.Type.DEVICE_NOTIFICATION) {
+ String message = event.getMessagePayload();
+ InputStream in = new ByteArrayInputStream(message.getBytes(StandardCharsets.UTF_8));
+ try {
+ Document doc = XmlEventParser.createDocFromMessage(in);
+ long timeStamp = XmlEventParser.getEventTime(doc);
+ Node descriptionNode = XmlEventParser.getDescriptionNode(doc);
+ while (descriptionNode != null) {
+ if (descriptionNode.getNodeType() == Node.ELEMENT_NODE) {
+ String nodeName = descriptionNode.getNodeName();
+ if (nodeName == "port-power-alarm") {
+ Node portIdNode = descriptionNode.getChildNodes().item(1);
+ String portId = portIdNode.getTextContent();
+ String description = "Loss of Service alarm raised for fibre " + portId;
+ alarms.add(new DefaultAlarm.Builder(AlarmId.alarmId(deviceId,
+ Long.toString(timeStamp)), deviceId, description,
+ Alarm.SeverityLevel.MAJOR, timeStamp).build());
+ descriptionNode = null;
+ }
+ } else {
+ descriptionNode = descriptionNode.getNextSibling();
+ }
+ }
+ } catch (SAXException | IOException | ParserConfigurationException |
+ UnsupportedOperationException | IllegalArgumentException e) {
+ log.error("Exception thrown translating message from {}.", deviceId, e);
+ }
+ }
+ }
+ }
+ return alarms;
+ }
+}
diff --git a/drivers/polatis/netconf/src/main/resources/polatis-drivers.xml b/drivers/polatis/netconf/src/main/resources/polatis-drivers.xml
index 0c36cbc..f95cbe2 100644
--- a/drivers/polatis/netconf/src/main/resources/polatis-drivers.xml
+++ b/drivers/polatis/netconf/src/main/resources/polatis-drivers.xml
@@ -27,6 +27,8 @@
impl="org.onosproject.drivers.polatis.netconf.PolatisFlowRuleProgrammable"/>
<behaviour api="org.onosproject.incubator.net.faultmanagement.alarm.AlarmConsumer"
impl="org.onosproject.drivers.polatis.netconf.PolatisAlarmConsumer"/>
+ <behaviour api="org.onosproject.incubator.net.faultmanagement.alarm.DeviceAlarmConfig"
+ impl="org.onosproject.drivers.polatis.netconf.PolatisAlarmConfig"/>
<property name="uiType">policon</property>
<property name="notificationStream">Polatis</property>
</driver>
diff --git a/drivers/utilities/src/main/java/org/onosproject/drivers/utilities/XmlConfigParser.java b/drivers/utilities/src/main/java/org/onosproject/drivers/utilities/XmlConfigParser.java
index e804a81..5fdca6d 100644
--- a/drivers/utilities/src/main/java/org/onosproject/drivers/utilities/XmlConfigParser.java
+++ b/drivers/utilities/src/main/java/org/onosproject/drivers/utilities/XmlConfigParser.java
@@ -34,7 +34,6 @@
import java.util.ArrayList;
import java.util.List;
-
/**
* Parser for Netconf XML configurations and replys.
*/
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/faultmanagement/alarm/XmlEventParser.java b/incubator/api/src/main/java/org/onosproject/incubator/net/faultmanagement/alarm/XmlEventParser.java
new file mode 100644
index 0000000..6ed2d7a
--- /dev/null
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/faultmanagement/alarm/XmlEventParser.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2018-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.incubator.net.faultmanagement.alarm;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.time.Instant;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * Parser for Netconf notifications.
+ */
+public final class XmlEventParser {
+ public static final Logger log = LoggerFactory
+ .getLogger(XmlEventParser.class);
+
+ private static final String DISALLOW_DTD_FEATURE = "http://apache.org/xml/features/disallow-doctype-decl";
+ private static final String DISALLOW_EXTERNAL_DTD =
+ "http://apache.org/xml/features/nonvalidating/load-external-dtd";
+ private static final String EVENTTIME_TAGNAME = "eventTime";
+
+ private XmlEventParser() {
+ }
+
+ /**
+ * Creates a document from the input stream message and returns the result.
+ *
+ * @param message input stream message
+ * @return the document result
+ * @throws SAXException Throws SAX Exception
+ * @throws IOException Throws IO Exception
+ * @throws ParserConfigurationException Throws ParserConfigurationException
+ */
+ public static Document createDocFromMessage(InputStream message)
+ throws SAXException, IOException, ParserConfigurationException {
+ DocumentBuilderFactory dbfactory = DocumentBuilderFactory.newInstance();
+ //Disabling DTDs in order to avoid XXE xml-based attacks.
+ disableFeature(dbfactory, DISALLOW_DTD_FEATURE);
+ disableFeature(dbfactory, DISALLOW_EXTERNAL_DTD);
+ dbfactory.setXIncludeAware(false);
+ dbfactory.setExpandEntityReferences(false);
+ DocumentBuilder builder = dbfactory.newDocumentBuilder();
+ return builder.parse(new InputSource(message));
+ }
+
+ private static void disableFeature(DocumentBuilderFactory dbfactory, String feature) {
+ try {
+ dbfactory.setFeature(feature, true);
+ } catch (ParserConfigurationException e) {
+ // This should catch a failed setFeature feature
+ log.info("ParserConfigurationException was thrown. The feature '" +
+ feature + "' is probably not supported by your XML processor.");
+ }
+ }
+
+ public static long getEventTime(Document doc)
+ throws UnsupportedOperationException, IllegalArgumentException {
+ String dateTime = getEventTimeNode(doc).getTextContent();
+ return DateTimeFormatter.ISO_DATE_TIME.parse(dateTime, Instant::from).getEpochSecond();
+ }
+
+ public static Node getDescriptionNode(Document doc) {
+ return getEventTimeNode(doc).getNextSibling();
+ }
+
+ private static Node getEventTimeNode(Document doc) {
+ return doc.getElementsByTagName(EVENTTIME_TAGNAME).item(0);
+ }
+}
diff --git a/providers/netconf/alarm/src/main/java/org/onosproject/provider/netconf/alarm/NetconfAlarmProvider.java b/providers/netconf/alarm/src/main/java/org/onosproject/provider/netconf/alarm/NetconfAlarmProvider.java
index 47790f3..ec4f8ae 100644
--- a/providers/netconf/alarm/src/main/java/org/onosproject/provider/netconf/alarm/NetconfAlarmProvider.java
+++ b/providers/netconf/alarm/src/main/java/org/onosproject/provider/netconf/alarm/NetconfAlarmProvider.java
@@ -16,6 +16,7 @@
package org.onosproject.provider.netconf.alarm;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.Maps;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
@@ -27,7 +28,15 @@
import org.onosproject.incubator.net.faultmanagement.alarm.AlarmProviderService;
import org.onosproject.incubator.net.faultmanagement.alarm.AlarmProviderRegistry;
import org.onosproject.incubator.net.faultmanagement.alarm.AlarmTranslator;
+import org.onosproject.incubator.net.faultmanagement.alarm.DeviceAlarmConfig;
+import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.driver.DefaultDriverData;
+import org.onosproject.net.driver.DefaultDriverHandler;
+import org.onosproject.net.driver.Driver;
+import org.onosproject.net.driver.DriverData;
+import org.onosproject.net.driver.DriverService;
import org.onosproject.net.provider.AbstractProvider;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.netconf.FilteringNetconfDeviceOutputEventListener;
@@ -45,6 +54,7 @@
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.Map;
+import java.util.Set;
import static org.slf4j.LoggerFactory.getLogger;
@@ -64,6 +74,12 @@
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected NetconfController controller;
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected DriverService driverService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected DeviceService deviceService;
+
protected AlarmProviderService providerService;
private Map<DeviceId, InternalNotificationListener> idNotificationListenerMap = Maps.newHashMap();
@@ -123,10 +139,20 @@
public void event(NetconfDeviceOutputEvent event) {
if (event.type() == NetconfDeviceOutputEvent.Type.DEVICE_NOTIFICATION) {
DeviceId deviceId = event.getDeviceInfo().getDeviceId();
- String message = event.getMessagePayload();
- InputStream in = new ByteArrayInputStream(message.getBytes(StandardCharsets.UTF_8));
- Collection<Alarm> newAlarms = translator.translateToAlarm(deviceId, in);
- triggerProbe(deviceId, newAlarms);
+ Driver deviceDriver = driverService.getDriver(deviceId);
+ Device device = deviceService.getDevice(deviceId);
+ if (deviceDriver != null && device.is(DeviceAlarmConfig.class)) {
+ DeviceAlarmConfig alarmTranslator = device.as(DeviceAlarmConfig.class);
+ DriverData driverData = new DefaultDriverData(deviceDriver, deviceId);
+ alarmTranslator.setHandler(new DefaultDriverHandler(driverData));
+ Set<Alarm> alarms = alarmTranslator.translateAlarms(ImmutableList.of(event));
+ triggerProbe(deviceId, alarms);
+ } else {
+ String message = event.getMessagePayload();
+ InputStream in = new ByteArrayInputStream(message.getBytes(StandardCharsets.UTF_8));
+ Collection<Alarm> newAlarms = translator.translateToAlarm(deviceId, in);
+ triggerProbe(deviceId, newAlarms);
+ }
}
}
}
diff --git a/providers/netconf/alarm/src/main/java/org/onosproject/provider/netconf/alarm/NetconfAlarmTranslator.java b/providers/netconf/alarm/src/main/java/org/onosproject/provider/netconf/alarm/NetconfAlarmTranslator.java
index a614635..05847e1 100644
--- a/providers/netconf/alarm/src/main/java/org/onosproject/provider/netconf/alarm/NetconfAlarmTranslator.java
+++ b/providers/netconf/alarm/src/main/java/org/onosproject/provider/netconf/alarm/NetconfAlarmTranslator.java
@@ -21,14 +21,12 @@
import org.onosproject.incubator.net.faultmanagement.alarm.AlarmId;
import org.onosproject.incubator.net.faultmanagement.alarm.AlarmTranslator;
import org.onosproject.incubator.net.faultmanagement.alarm.DefaultAlarm;
+import org.onosproject.incubator.net.faultmanagement.alarm.XmlEventParser;
import org.onosproject.net.DeviceId;
import org.slf4j.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
-import org.xml.sax.InputSource;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
@@ -39,8 +37,6 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
-import java.time.Instant;
-import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collection;
@@ -56,24 +52,13 @@
private final Logger log = getLogger(getClass());
private static final String EVENTTIME_TAGNAME = "eventTime";
- private static final String DISALLOW_DTD_FEATURE = "http://apache.org/xml/features/disallow-doctype-decl";
-
- private static final String DISALLOW_EXTERNAL_DTD =
- "http://apache.org/xml/features/nonvalidating/load-external-dtd";
-
@Override
public Collection<Alarm> translateToAlarm(DeviceId deviceId, InputStream message) {
try {
Collection<Alarm> alarms = new ArrayList<>();
- Document doc = createDocFromMessage(message);
-
- // parse date element value into long
- Node eventTime = doc.getElementsByTagName(EVENTTIME_TAGNAME).item(0);
- String date = eventTime.getTextContent();
- long timeStamp = parseDate(date);
-
- // event-specific tag names as alarm descriptions
- Node descriptionNode = eventTime.getNextSibling();
+ Document doc = XmlEventParser.createDocFromMessage(message);
+ long timeStamp = XmlEventParser.getEventTime(doc);
+ Node descriptionNode = XmlEventParser.getDescriptionNode(doc);
while (descriptionNode != null) {
if (descriptionNode.getNodeType() == Node.ELEMENT_NODE) {
String description = nodeToString(descriptionNode);
@@ -95,33 +80,6 @@
}
}
- private Document createDocFromMessage(InputStream message)
- throws SAXException, IOException, ParserConfigurationException {
- DocumentBuilderFactory dbfactory = DocumentBuilderFactory.newInstance();
- //Disabling DTDs in order to avoid XXE xml-based attacks.
- disableFeature(dbfactory, DISALLOW_DTD_FEATURE);
- disableFeature(dbfactory, DISALLOW_EXTERNAL_DTD);
- dbfactory.setXIncludeAware(false);
- dbfactory.setExpandEntityReferences(false);
- DocumentBuilder builder = dbfactory.newDocumentBuilder();
- return builder.parse(new InputSource(message));
- }
-
- private void disableFeature(DocumentBuilderFactory dbfactory, String feature) {
- try {
- dbfactory.setFeature(feature, true);
- } catch (ParserConfigurationException e) {
- // This should catch a failed setFeature feature
- log.info("ParserConfigurationException was thrown. The feature '" +
- feature + "' is probably not supported by your XML processor.");
- }
- }
-
- private long parseDate(String timeStr)
- throws UnsupportedOperationException, IllegalArgumentException {
- return DateTimeFormatter.ISO_DATE_TIME.parse(timeStr, Instant::from).getEpochSecond();
- }
-
private static String nodeToString(Node rootNode) throws TransformerException {
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
@@ -131,4 +89,4 @@
transformer.transform(source, new StreamResult(writer));
return writer.getBuffer().toString();
}
-}
\ No newline at end of file
+}