Development of NETCONF RPCs for tr-069 adapter to
[oam/tr069-adapter.git] / netconf-server / src / main / java / org / commscope / tr069adapter / netconf / rpc / CreateSubscription.java
index a5ac333..70350f8 100644 (file)
-/*\r
- * ============LICENSE_START========================================================================\r
- * ONAP : tr-069-adapter\r
- * =================================================================================================\r
- * Copyright (C) 2020 CommScope Inc Intellectual Property.\r
- * =================================================================================================\r
- * This tr-069-adapter software file is distributed by CommScope Inc under the Apache License,\r
- * Version 2.0 (the "License"); you may not use this file except in compliance with the License. You\r
- * may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,\r
- * either express or implied. See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- * ===============LICENSE_END=======================================================================\r
- */\r
-\r
-package org.commscope.tr069adapter.netconf.rpc;\r
-\r
-import java.io.File;\r
-import java.io.IOException;\r
-import java.text.SimpleDateFormat;\r
-import java.util.Collection;\r
-import java.util.Collections;\r
-import java.util.Date;\r
-import java.util.HashMap;\r
-import java.util.List;\r
-import java.util.Map;\r
-import java.util.Optional;\r
-import java.util.concurrent.Executors;\r
-import java.util.concurrent.ScheduledExecutorService;\r
-import java.util.concurrent.TimeUnit;\r
-import javax.xml.bind.JAXBContext;\r
-import javax.xml.bind.JAXBException;\r
-import javax.xml.bind.Unmarshaller;\r
-import javax.xml.bind.annotation.XmlRootElement;\r
-import org.commscope.tr069adapter.netconf.error.NetconfNotificationException;\r
-import org.opendaylight.netconf.api.NetconfMessage;\r
-import org.opendaylight.netconf.api.xml.XmlElement;\r
-import org.opendaylight.netconf.api.xml.XmlNetconfConstants;\r
-import org.opendaylight.netconf.api.xml.XmlUtil;\r
-import org.opendaylight.netconf.impl.NetconfServerSession;\r
-import org.opendaylight.netconf.impl.mapping.operations.DefaultNetconfOperation;\r
-import org.opendaylight.netconf.util.mapping.AbstractLastNetconfOperation;\r
-import org.slf4j.Logger;\r
-import org.slf4j.LoggerFactory;\r
-import org.w3c.dom.Document;\r
-import org.w3c.dom.Element;\r
-import org.xml.sax.SAXException;\r
-import com.google.common.base.Preconditions;\r
-import com.google.common.collect.Maps;\r
-\r
-public class CreateSubscription extends AbstractLastNetconfOperation\r
-    implements DefaultNetconfOperation {\r
-\r
-  private static final Logger logger = LoggerFactory.getLogger(CreateSubscription.class);\r
-  private final Map<Notification, NetconfMessage> notifications;\r
-  private NetconfServerSession session;\r
-  private ScheduledExecutorService scheduledExecutorService;\r
-  private static Map<String, NetconfServerSession> netconfServerSessionMap = new HashMap<>();\r
-  private String deviceID;\r
-  private String swVersion;\r
-  private String hwVersion;\r
-\r
-  public CreateSubscription(final String id, final Optional<File> notificationsFile,\r
-      String deviceID, String swVersion, String hwVersion) {\r
-\r
-    super(id);\r
-\r
-    logger.debug("CreateSubscription RPC is created with macID {}", deviceID);\r
-    this.deviceID = deviceID;\r
-    this.swVersion = swVersion;\r
-    this.hwVersion = hwVersion;\r
-\r
-    final Optional<Notifications> notifs;\r
-\r
-    if (notificationsFile.isPresent()) {\r
-      notifs = Optional.of(loadNotifications(notificationsFile.get()));\r
-      scheduledExecutorService = Executors.newScheduledThreadPool(1);\r
-    } else {\r
-      notifs = Optional.empty();\r
-    }\r
-\r
-    if (notifs.isPresent()) {\r
-      final Collection<Notification> toCopy = notifs.get().getNotificationList();\r
-      final Map<Notification, NetconfMessage> preparedMessages =\r
-          Maps.newHashMapWithExpectedSize(toCopy.size());\r
-      for (final Notification notification : toCopy) {\r
-        final NetconfMessage parsedNotification =\r
-            parseNetconfNotification(notification.getContent());\r
-        preparedMessages.put(notification, parsedNotification);\r
-      }\r
-      this.notifications = preparedMessages;\r
-    } else {\r
-      this.notifications = Collections.emptyMap();\r
-    }\r
-  }\r
-\r
-  private static Notifications loadNotifications(final File file) {\r
-    try {\r
-      final JAXBContext jaxbContext = JAXBContext.newInstance(Notifications.class);\r
-      final Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();\r
-      return (Notifications) jaxbUnmarshaller.unmarshal(file);\r
-    } catch (final JAXBException e) {\r
-      throw new IllegalArgumentException("can not parse file " + file + " as a notifications file",\r
-          e);\r
-    }\r
-  }\r
-\r
-  @Override\r
-  protected String getOperationName() {\r
-    return "create-subscription";\r
-  }\r
-\r
-  @Override\r
-  protected String getOperationNamespace() {\r
-    return "urn:ietf:params:xml:ns:netconf:notification:1.0";\r
-  }\r
-\r
-  @Override\r
-  protected Element handleWithNoSubsequentOperations(final Document document,\r
-      final XmlElement operationElement) {\r
-    long delayAggregator = 0;\r
-    for (final Map.Entry<Notification, NetconfMessage> notification : notifications.entrySet()) {\r
-      for (int i = 0; i <= notification.getKey().getTimes(); i++) {\r
-\r
-        delayAggregator += notification.getKey().getDelayInSeconds();\r
-\r
-        scheduledExecutorService.schedule(() -> {\r
-          Preconditions.checkState(session != null,\r
-              "Session is not set, cannot process notifications");\r
-          session.sendMessage(notification.getValue());\r
-        }, delayAggregator, TimeUnit.SECONDS);\r
-      }\r
-    }\r
-    return document.createElement(XmlNetconfConstants.OK);\r
-  }\r
-\r
-  private static NetconfMessage parseNetconfNotification(String content) {\r
-    final int startEventTime = content.indexOf("<eventTime>") + "<eventTime>".length();\r
-    final int endEventTime = content.indexOf("</eventTime>");\r
-    final String eventTime = content.substring(startEventTime, endEventTime);\r
-    if (eventTime.equals("XXXX")) {\r
-      content = content.replace(eventTime,\r
-          new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX").format(new Date()));\r
-    }\r
-\r
-    try {\r
-      return new NetconfMessage(XmlUtil.readXmlToDocument(content));\r
-    } catch (SAXException | IOException e) {\r
-      throw new IllegalArgumentException("Cannot parse notifications", e);\r
-    }\r
-  }\r
-\r
-  @Override\r
-  public void setNetconfSession(final NetconfServerSession newSession) {\r
-    logger.debug("Adding netconf session to notification server sessions map : {}", newSession);\r
-    logger.debug("This CreateSubscription is setup to support  macID= {}", deviceID);\r
-    this.session = newSession;\r
-    netconfServerSessionMap.put(deviceID, newSession);\r
-  }\r
-\r
-  public static void sendNotification(NetconfMessage netconfMessage, String deviceID)\r
-      throws NetconfNotificationException {\r
-    logger.debug("Request to send notification. NetConfMessage : {}", netconfMessage);\r
-    NetconfServerSession session = netconfServerSessionMap.get(deviceID);\r
-    if (session != null && session.isUp()) {\r
-      try {\r
-        session.sendMessage(netconfMessage);\r
-        logger.debug("Successfully send notification for deviceID: {}", deviceID);\r
-      } catch (Exception e) {\r
-        logger.error("Failed to send notification. while posting got error. {}", e.toString());\r
-        throw new NetconfNotificationException("Exception while posting the netconf message", e);\r
-      }\r
-\r
-    } else {\r
-      logger.debug(\r
-          "Failed to send notification. None of valid netconf session is available for {}.",\r
-          deviceID);\r
-      logger.debug("Available netconf sessions : {}", netconfServerSessionMap);\r
-      throw new NetconfNotificationException("NetConf active session deosn't not exist");\r
-    }\r
-  }\r
-\r
-  @XmlRootElement(name = "notifications")\r
-  public static final class Notifications {\r
-\r
-    @javax.xml.bind.annotation.XmlElement(nillable = false, name = "notification", required = true)\r
-    private List<Notification> notificationList;\r
-\r
-    public List<Notification> getNotificationList() {\r
-      return notificationList;\r
-    }\r
-\r
-    @Override\r
-    public String toString() {\r
-      final StringBuilder sb = new StringBuilder("Notifications{");\r
-      sb.append("notificationList=").append(notificationList);\r
-      sb.append('}');\r
-      return sb.toString();\r
-    }\r
-  }\r
-\r
-  public static final class Notification {\r
-\r
-    @javax.xml.bind.annotation.XmlElement(nillable = false, name = "delay")\r
-    private long delayInSeconds;\r
-\r
-    @javax.xml.bind.annotation.XmlElement(nillable = false, name = "times")\r
-    private long times;\r
-\r
-    @javax.xml.bind.annotation.XmlElement(nillable = false, name = "content", required = true)\r
-    private String content;\r
-\r
-    public long getDelayInSeconds() {\r
-      return delayInSeconds;\r
-    }\r
-\r
-    public long getTimes() {\r
-      return times;\r
-    }\r
-\r
-    public String getContent() {\r
-      return content;\r
-    }\r
-\r
-    @Override\r
-    public String toString() {\r
-      final StringBuilder sb = new StringBuilder("Notification{");\r
-      sb.append("delayInSeconds=").append(delayInSeconds);\r
-      sb.append(", times=").append(times);\r
-      sb.append(", content='").append(content).append('\'');\r
-      sb.append('}');\r
-      return sb.toString();\r
-    }\r
-  }\r
-}\r
+/*
+ * ============LICENSE_START========================================================================
+ * ONAP : tr-069-adapter
+ * =================================================================================================
+ * Copyright (C) 2020 CommScope Inc Intellectual Property.
+ * =================================================================================================
+ * This tr-069-adapter software file is distributed by CommScope Inc 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
+ *
+ * This file 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.
+ * ===============LICENSE_END=======================================================================
+ */
+
+package org.commscope.tr069adapter.netconf.rpc;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Maps;
+
+import java.io.File;
+import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.bind.annotation.XmlRootElement;
+import org.commscope.tr069adapter.netconf.error.NetconfNotificationException;
+import org.opendaylight.netconf.api.NetconfMessage;
+import org.opendaylight.netconf.api.xml.XmlElement;
+import org.opendaylight.netconf.api.xml.XmlNetconfConstants;
+import org.opendaylight.netconf.api.xml.XmlUtil;
+import org.opendaylight.netconf.impl.NetconfServerSession;
+import org.opendaylight.netconf.impl.mapping.operations.DefaultNetconfOperation;
+import org.opendaylight.netconf.util.mapping.AbstractLastNetconfOperation;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.xml.sax.SAXException;
+
+public class CreateSubscription extends AbstractLastNetconfOperation
+    implements DefaultNetconfOperation {
+
+  private static final Logger logger = LoggerFactory.getLogger(CreateSubscription.class);
+  private final Map<Notification, NetconfMessage> notifications;
+  private NetconfServerSession session;
+  private ScheduledExecutorService scheduledExecutorService;
+  private static Map<String, NetconfServerSession> netconfServerSessionMap = new HashMap<>();
+  private String deviceID;
+  private String swVersion;
+  private String hwVersion;
+
+  public CreateSubscription(final String id, final Optional<File> notificationsFile,
+      String deviceID, String swVersion, String hwVersion) {
+
+    super(id);
+
+    logger.debug("CreateSubscription RPC is created with macID {}", deviceID);
+    this.deviceID = deviceID;
+    this.swVersion = swVersion;
+    this.hwVersion = hwVersion;
+
+    final Optional<Notifications> notifs;
+
+    if (notificationsFile.isPresent()) {
+      notifs = Optional.of(loadNotifications(notificationsFile.get()));
+      scheduledExecutorService = Executors.newScheduledThreadPool(1);
+    } else {
+      notifs = Optional.empty();
+    }
+
+    if (notifs.isPresent()) {
+      final Collection<Notification> toCopy = notifs.get().getNotificationList();
+      final Map<Notification, NetconfMessage> preparedMessages =
+          Maps.newHashMapWithExpectedSize(toCopy.size());
+      for (final Notification notification : toCopy) {
+        final NetconfMessage parsedNotification =
+            parseNetconfNotification(notification.getContent());
+        preparedMessages.put(notification, parsedNotification);
+      }
+      this.notifications = preparedMessages;
+    } else {
+      this.notifications = Collections.emptyMap();
+    }
+  }
+
+  private static Notifications loadNotifications(final File file) {
+    try {
+      final JAXBContext jaxbContext = JAXBContext.newInstance(Notifications.class);
+      final Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
+      return (Notifications) jaxbUnmarshaller.unmarshal(file);
+    } catch (final JAXBException e) {
+      throw new IllegalArgumentException("can not parse file " + file + " as a notifications file",
+          e);
+    }
+  }
+
+  @Override
+  protected String getOperationName() {
+    return "create-subscription";
+  }
+
+  @Override
+  protected String getOperationNamespace() {
+    return "urn:ietf:params:xml:ns:netconf:notification:1.0";
+  }
+
+  @Override
+  protected Element handleWithNoSubsequentOperations(final Document document,
+      final XmlElement operationElement) {
+    long delayAggregator = 0;
+    for (final Map.Entry<Notification, NetconfMessage> notification : notifications.entrySet()) {
+      for (int i = 0; i <= notification.getKey().getTimes(); i++) {
+
+        delayAggregator += notification.getKey().getDelayInSeconds();
+
+        scheduledExecutorService.schedule(() -> {
+          Preconditions.checkState(session != null,
+              "Session is not set, cannot process notifications");
+          session.sendMessage(notification.getValue());
+        }, delayAggregator, TimeUnit.SECONDS);
+      }
+    }
+    return document.createElement(XmlNetconfConstants.OK);
+  }
+
+  private static NetconfMessage parseNetconfNotification(String content) {
+    final int startEventTime = content.indexOf("<eventTime>") + "<eventTime>".length();
+    final int endEventTime = content.indexOf("</eventTime>");
+    final String eventTime = content.substring(startEventTime, endEventTime);
+    if (eventTime.equals("XXXX")) {
+      content = content.replace(eventTime,
+          new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX").format(new Date()));
+    }
+
+    try {
+      return new NetconfMessage(XmlUtil.readXmlToDocument(content));
+    } catch (SAXException | IOException e) {
+      throw new IllegalArgumentException("Cannot parse notifications", e);
+    }
+  }
+
+  @Override
+  public void setNetconfSession(final NetconfServerSession newSession) {
+    logger.debug("Adding netconf session to notification server sessions map : {}", newSession);
+    logger.debug("This CreateSubscription is setup to support  macID= {}", deviceID);
+    this.session = newSession;
+    netconfServerSessionMap.put(deviceID, newSession);
+  }
+
+  public static void sendNotification(NetconfMessage netconfMessage, String deviceID)
+      throws NetconfNotificationException {
+    logger.debug("Request to send notification. NetConfMessage : {}", netconfMessage);
+    NetconfServerSession session = netconfServerSessionMap.get(deviceID);
+    if (session != null && session.isUp()) {
+      try {
+        session.sendMessage(netconfMessage);
+        logger.debug("Successfully send notification for deviceID: {}", deviceID);
+      } catch (Exception e) {
+        logger.error("Failed to send notification. while posting got error. {}", e.toString());
+        throw new NetconfNotificationException("Exception while posting the netconf message", e);
+      }
+
+    } else {
+      logger.debug(
+          "Failed to send notification. None of valid netconf session is available for {}.",
+          deviceID);
+      logger.debug("Available netconf sessions : {}", netconfServerSessionMap);
+      throw new NetconfNotificationException("NetConf active session deosn't not exist");
+    }
+  }
+
+  @XmlRootElement(name = "notifications")
+  public static final class Notifications {
+
+    @javax.xml.bind.annotation.XmlElement(nillable = false, name = "notification", required = true)
+    private List<Notification> notificationList;
+
+    public List<Notification> getNotificationList() {
+      return notificationList;
+    }
+
+    @Override
+    public String toString() {
+      final StringBuilder sb = new StringBuilder("Notifications{");
+      sb.append("notificationList=").append(notificationList);
+      sb.append('}');
+      return sb.toString();
+    }
+  }
+
+  public static final class Notification {
+
+    @javax.xml.bind.annotation.XmlElement(nillable = false, name = "delay")
+    private long delayInSeconds;
+
+    @javax.xml.bind.annotation.XmlElement(nillable = false, name = "times")
+    private long times;
+
+    @javax.xml.bind.annotation.XmlElement(nillable = false, name = "content", required = true)
+    private String content;
+
+    public long getDelayInSeconds() {
+      return delayInSeconds;
+    }
+
+    public long getTimes() {
+      return times;
+    }
+
+    public String getContent() {
+      return content;
+    }
+
+    @Override
+    public String toString() {
+      final StringBuilder sb = new StringBuilder("Notification{");
+      sb.append("delayInSeconds=").append(delayInSeconds);
+      sb.append(", times=").append(times);
+      sb.append(", content='").append(content).append('\'');
+      sb.append('}');
+      return sb.toString();
+    }
+  }
+}