Initial source code
[oam/tr069-adapter.git] / netconf-server / src / main / java / org / commscope / tr069adapter / netconf / server / NetconfServerStarter.java
diff --git a/netconf-server/src/main/java/org/commscope/tr069adapter/netconf/server/NetconfServerStarter.java b/netconf-server/src/main/java/org/commscope/tr069adapter/netconf/server/NetconfServerStarter.java
new file mode 100644 (file)
index 0000000..39e4e3b
--- /dev/null
@@ -0,0 +1,182 @@
+/*\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.server;\r
+\r
+import java.io.BufferedReader;\r
+import java.io.File;\r
+import java.io.FileReader;\r
+import java.io.IOException;\r
+import java.util.Arrays;\r
+import java.util.Collections;\r
+import java.util.List;\r
+import java.util.concurrent.TimeUnit;\r
+import java.util.regex.Matcher;\r
+import java.util.regex.Pattern;\r
+import org.commscope.tr069adapter.netconf.config.NetConfServerProperties;\r
+import org.commscope.tr069adapter.netconf.operations.CustomOperationsCreator;\r
+import org.opendaylight.netconf.test.tool.NetconfDeviceSimulator;\r
+import org.opendaylight.netconf.test.tool.config.Configuration;\r
+import org.opendaylight.netconf.test.tool.config.ConfigurationBuilder;\r
+import org.opendaylight.netconf.test.tool.operations.OperationsCreator;\r
+import org.slf4j.Logger;\r
+import org.slf4j.LoggerFactory;\r
+import org.springframework.beans.factory.annotation.Autowired;\r
+import org.springframework.context.annotation.Scope;\r
+import org.springframework.stereotype.Component;\r
+import com.google.common.base.Preconditions;\r
+\r
+@Component\r
+@Scope("singleton")\r
+public class NetconfServerStarter {\r
+\r
+  private static final Logger LOG = LoggerFactory.getLogger(NetconfServerStarter.class);\r
+\r
+  @Autowired\r
+  NetConfServerProperties config;\r
+\r
+  public boolean startServer(String netConfPort, String macID) {\r
+\r
+    if (netConfPort == null) {\r
+      LOG.error("Invalid NETCONF port for deviceID: {}, port is null.", macID);\r
+      return false;\r
+    }\r
+\r
+    LOG.debug("Starting Netconf server for MACID :{}, on port :{}", macID, netConfPort);\r
+    boolean result = startServer(netConfPort, config.getSchemaDirPath(), macID);\r
+    LOG.debug("Completed starting Netconf server for MACID :{} , on port :{}, server status={}",\r
+        macID, netConfPort, result);\r
+\r
+    return result;\r
+  }\r
+\r
+  @SuppressWarnings({"resource", "deprecation"})\r
+  private boolean startServer(String portStr, String schemaDirPath, String macID) {\r
+\r
+    // creating configuration for the netconf instance\r
+    final Configuration configuration = new ConfigurationBuilder().build();\r
+    OperationsCreator operationsCreator = new CustomOperationsCreator(macID);\r
+    configuration.setOperationsCreator(operationsCreator);\r
+    configuration.setGenerateConfigsTimeout((int) TimeUnit.MINUTES.toMillis(30));\r
+    if (portStr != null) {\r
+      try {\r
+        int port = Integer.parseInt(portStr);\r
+        configuration.setStartingPort(port);\r
+      } catch (Exception e) {\r
+        LOG.error("Failed to get netconf service instance port for parameters {}", e.toString());\r
+        return false;\r
+      }\r
+    }\r
+    configuration.setDeviceCount(1);\r
+    configuration.setSsh(Boolean.TRUE);\r
+    File schemaDir = new File(schemaDirPath);\r
+    configuration.setSchemasDir(schemaDir);\r
+    configuration.setCapabilities(Configuration.DEFAULT_BASE_CAPABILITIES_EXI);\r
+    configuration.setIp("0.0.0.0");\r
+\r
+    boolean isSchemaLoaded = loadSchemas(schemaDir);\r
+    if (!isSchemaLoaded) {\r
+      LOG.debug("Failed to load schema for netconf server instance {}", macID);\r
+      return false;\r
+    }\r
+\r
+    try(final NetconfDevice netconfDevice = new NetconfDevice(configuration)){\r
+      final List<Integer> openDevices = netconfDevice.start();\r
+      if (openDevices.isEmpty()) {\r
+        LOG.debug("Failed to start netconf server instance {}", macID);\r
+        return false;\r
+      }\r
+      netconfDevice.setAutoClose(false);\r
+    } catch (RuntimeException e) {\r
+      LOG.error("Unhandled exception. Failed to start the server", e);\r
+      return false;\r
+    }\r
+\r
+    return true;\r
+  }\r
+\r
+  private boolean loadSchemas(File schemasDir) {\r
+    if (schemasDir != null) {\r
+      if (!schemasDir.exists() || !schemasDir.isDirectory() || !schemasDir.canRead()) {\r
+        LOG.error("Failed to load schema. schema location is not valid.");\r
+        return false;\r
+      }\r
+\r
+      Pattern yangregex = Pattern.compile("(?<name>.*)@(?<revision>\\d{4}-\\d{2}-\\d{2})\\.yang");\r
+      Pattern revisionregex = Pattern.compile("revision\\s+\"?(\\d{4}-\\d{2}-\\d{2})\"?");\r
+\r
+      final File[] filesArray = schemasDir.listFiles();\r
+      final List<File> files =\r
+          filesArray != null ? Arrays.asList(filesArray) : Collections.emptyList();\r
+      for (final File file : files) {\r
+        final Matcher yangMatcher = yangregex.matcher(file.getName());\r
+        if (!yangMatcher.matches()) {\r
+          try (BufferedReader reader = new BufferedReader(new FileReader(file))) {\r
+            String line = reader.readLine();\r
+            while (line != null && !revisionregex.matcher(line).find()) {\r
+              line = reader.readLine();\r
+            }\r
+            loadSchemaPattren(line, file, revisionregex);\r
+          } catch (final IOException e) {\r
+            LOG.error("Unhandled exception. Failed to load the schema.{}", e.toString());\r
+            return false;\r
+          }\r
+        }\r
+      }\r
+    }\r
+    return true;\r
+  }\r
+\r
+  private void loadSchemaPattren(String line, File file, Pattern revisionregex) {\r
+    if (line != null) {\r
+      final Matcher m = revisionregex.matcher(line);\r
+      Preconditions.checkState(m.find());\r
+      String moduleName = file.getAbsolutePath();\r
+      if (file.getName().endsWith(".yang")) {\r
+        moduleName = moduleName.substring(0, moduleName.length() - 5);\r
+      }\r
+      final String revision = m.group(1);\r
+      final String correctName = moduleName + "@" + revision + ".yang";\r
+      final File correctNameFile = new File(correctName);\r
+      if (!file.renameTo(correctNameFile)) {\r
+        throw new IllegalStateException("Failed to rename '%s'." + file);\r
+      }\r
+    }\r
+  }\r
+\r
+}\r
+\r
+\r
+class NetconfDevice extends NetconfDeviceSimulator {\r
+  boolean autoClose = true;\r
+\r
+  public NetconfDevice(Configuration configuration) {\r
+    super(configuration);\r
+  }\r
+\r
+  @Override\r
+  public void close() {\r
+    if (autoClose)\r
+      super.close();\r
+  }\r
+\r
+  public void setAutoClose(boolean autoClose) {\r
+    this.autoClose = autoClose;\r
+  }\r
+\r
+}\r