Initial source code
[oam/tr069-adapter.git] / netconf-server / src / main / java / org / commscope / tr069adapter / netconf / server / NetConfServerManagerImpl.java
diff --git a/netconf-server/src/main/java/org/commscope/tr069adapter/netconf/server/NetConfServerManagerImpl.java b/netconf-server/src/main/java/org/commscope/tr069adapter/netconf/server/NetConfServerManagerImpl.java
new file mode 100644 (file)
index 0000000..eee8db6
--- /dev/null
@@ -0,0 +1,250 @@
+/*\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.net.URI;\r
+import java.net.URISyntaxException;\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+import java.util.Map;\r
+import java.util.Map.Entry;\r
+\r
+import org.commscope.tr069adapter.mapper.model.NetConfServerDetails;\r
+import org.commscope.tr069adapter.mapper.model.NetconfServerManagementError;\r
+import org.commscope.tr069adapter.netconf.config.NetConfServerProperties;\r
+import org.commscope.tr069adapter.netconf.dao.NetConfServerDetailsRepository;\r
+import org.commscope.tr069adapter.netconf.entity.NetConfServerDetailsEntity;\r
+import org.commscope.tr069adapter.netconf.error.RetryFailedException;\r
+import org.commscope.tr069adapter.netconf.error.ServerPortAllocationException;\r
+import org.commscope.tr069adapter.netconf.server.helper.ServerPortAllocationHelper;\r
+import org.slf4j.Logger;\r
+import org.slf4j.LoggerFactory;\r
+import org.springframework.beans.factory.annotation.Autowired;\r
+import org.springframework.http.HttpEntity;\r
+import org.springframework.http.HttpHeaders;\r
+import org.springframework.stereotype.Component;\r
+import org.springframework.web.client.RestTemplate;\r
+\r
+@Component\r
+public class NetConfServerManagerImpl {\r
+\r
+  private static final Logger LOG = LoggerFactory.getLogger(NetConfServerManagerImpl.class);\r
+\r
+  @Autowired\r
+  ServerPortAllocationHelper serverPortAllocator;\r
+\r
+  @Autowired\r
+  NetConfServerDetailsRepository netconfDAO;\r
+\r
+  @Autowired\r
+  NetConfServerProperties config;\r
+\r
+  @Autowired\r
+  NetconfServerStarter ncServerStarter;\r
+\r
+  @Autowired\r
+  RestartNetconfServerHandler restartServersHandler;\r
+\r
+  public void restartServers() {\r
+    LOG.debug("Restarting all netconf servers during startup...");\r
+    Iterable<NetConfServerDetailsEntity> entities = netconfDAO.findAll();\r
+    List<NetConfServerDetailsEntity> serverDetailsList = new ArrayList<>();\r
+    for (NetConfServerDetailsEntity entity : entities) {\r
+      serverDetailsList.add(entity);\r
+    }\r
+    restartServersOnStartup(serverDetailsList);\r
+\r
+    if (!serverDetailsList.isEmpty()) {\r
+      LOG.debug("Attempting to start failed netconf servers {}", serverDetailsList);\r
+      try {\r
+        restartServersHandler.restart(serverDetailsList);\r
+      } catch (RetryFailedException e) {\r
+        LOG.error("Failed to restart all netconf servers. {}", e.toString());\r
+      }\r
+    }\r
+    LOG.debug("Restarting netconf servers during startup is completed.");\r
+  }\r
+\r
+  public NetConfServerDetails createServer(String deviceId, String enodeBName) {\r
+    NetConfServerDetails result = new NetConfServerDetails();\r
+    NetConfServerDetailsEntity entity = null;\r
+    if (deviceId != null) {\r
+      entity = netconfDAO.findByDeviceId(deviceId);\r
+    } else if (enodeBName != null) {\r
+      entity = netconfDAO.findByEnodeBName(enodeBName);\r
+    } else {\r
+      // none is specified\r
+      LOG.error(\r
+          "Both deviceID and enodeBName are null. Hence failed to create the netconf server.");\r
+      return null;\r
+    }\r
+\r
+    if (null != entity) {\r
+      // found the entity. server is already running. double check and run\r
+      // if\r
+      // required. else return the details.\r
+\r
+      // update the ENB Name if Changed\r
+      entity.setEnodeBName(enodeBName);\r
+      netconfDAO.save(entity);\r
+      result = getNetConfServerDetails(deviceId, entity);\r
+      return result;\r
+    }\r
+\r
+    try {\r
+\r
+      String port = serverPortAllocator.reserveServerPort();\r
+      LOG.debug("Successfully reserved a port for deviceID={} ,port={}", deviceId, port);\r
+\r
+      // start the server\r
+      boolean isServerStarted = ncServerStarter.startServer(port, deviceId);\r
+      boolean isPortInUse = serverPortAllocator.isServerPortInUse(port);\r
+\r
+      if (!isServerStarted || !isPortInUse) {\r
+        LOG.error(\r
+            "Failed to start netconf server for deviceID: {}, at port:{} , isServerStarted={} ,isPortInUse={}",\r
+            deviceId, port, isServerStarted, isPortInUse);\r
+        return null;\r
+      }\r
+\r
+      // save the record in db\r
+      entity = new NetConfServerDetailsEntity();\r
+      entity.setDeviceId(deviceId);\r
+      entity.setListenPort(port);\r
+      entity.setEnodeBName(enodeBName);\r
+      netconfDAO.save(entity);\r
+\r
+      result = getNetConfServerDetails(deviceId, entity);\r
+      LOG.debug("Successfully started netconf server for deviceID= {}, port={}", deviceId, port);\r
+\r
+    } catch (ServerPortAllocationException e) {\r
+      LOG.error("Failed to allocate a port {}", e.toString());\r
+    }\r
+\r
+    if (entity != null) {\r
+      result.setDeviceId(deviceId);\r
+      result.setListenPort(entity.getListenPort());\r
+      String netconfListenAddress = getServiceHost();\r
+      if (netconfListenAddress == null) {\r
+        netconfListenAddress = config.getNetconfServerIP();\r
+      }\r
+      result.setListenAddress(netconfListenAddress);\r
+      result.setError(NetconfServerManagementError.SUCCESS);\r
+    }\r
+    return result;\r
+  }\r
+\r
+  public void restartServersOnStartup(List<NetConfServerDetailsEntity> serverDetailsList) {\r
+\r
+    List<NetConfServerDetailsEntity> startedServers = new ArrayList<>();\r
+    for (NetConfServerDetailsEntity entity : serverDetailsList) {\r
+\r
+      serverPortAllocator.checkAndReserveServerPort(entity.getListenPort());\r
+\r
+      serverPortAllocator.isServerPortInUse(entity.getListenPort());\r
+      boolean isServerStarted =\r
+          ncServerStarter.startServer(entity.getListenPort(), entity.getDeviceId());\r
+\r
+      if (isServerStarted) {\r
+        LOG.info("Successfully restarted NETCONF server {}  on port {}  upon application startup.",\r
+            entity.getDeviceId(), entity.getListenPort());\r
+        // we need to push the pnfEntry for IP updated\r
+        NetConfServerDetails details = getNetConfServerDetails(entity.getDeviceId(), entity);\r
+\r
+        final String baseUrl = config.getMapperPath() + "/registerNetconfServer";\r
+        URI uri = null;\r
+        try {\r
+          uri = new URI(baseUrl);\r
+        } catch (URISyntaxException e) {\r
+          LOG.error("error while contructing the URI {}", e.toString());\r
+        }\r
+        RestTemplate restTemplate = new RestTemplate();\r
+        HttpHeaders headers = new HttpHeaders();\r
+        HttpEntity<NetConfServerDetails> httpentity = new HttpEntity<>(details, headers);\r
+        boolean isSuccess = false;\r
+        if (uri != null) {\r
+          isSuccess = restTemplate.postForObject(uri, httpentity, Boolean.class);\r
+        }\r
+\r
+        if (!isSuccess) {\r
+          LOG.error("Netconf Register request is failed update the updated host details..");\r
+        } else {\r
+          LOG.debug("successfully started the server");\r
+        }\r
+        startedServers.add(entity);\r
+      } else {\r
+        LOG.error("Failed to restart NETCONF server {}  on port {}  upon application startup.",\r
+            entity.getDeviceId(), entity.getListenPort());\r
+      }\r
+    }\r
+    if (!serverDetailsList.isEmpty()) {\r
+      serverDetailsList.removeAll(startedServers);\r
+    }\r
+  }\r
+\r
+  private NetConfServerDetails getNetConfServerDetails(String deviceId,\r
+      NetConfServerDetailsEntity entity) {\r
+    NetConfServerDetails result = new NetConfServerDetails();\r
+    result.setDeviceId(deviceId);\r
+    result.setListenPort(entity.getListenPort());\r
+    result.setEnodeBName(entity.getEnodeBName());\r
+    String netconfListenAddress = getServiceHost();\r
+    if (netconfListenAddress == null) {\r
+      netconfListenAddress = config.getNetconfServerIP();\r
+    }\r
+    result.setListenAddress(netconfListenAddress);\r
+    result.setError(NetconfServerManagementError.SUCCESS);\r
+    return result;\r
+  }\r
+\r
+  public boolean unregister(String deviceId, String enodeBName) {\r
+    LOG.debug("Unregister is not yet supported deviceId={} enodeBName={}", deviceId, enodeBName);\r
+    return false;\r
+  }\r
+\r
+  public List<NetConfServerDetails> getServersInfo() {\r
+    Iterable<NetConfServerDetailsEntity> serverEntities = netconfDAO.findAll();\r
+    String netconfListenAddress = getServiceHost();\r
+    if (netconfListenAddress == null) {\r
+      netconfListenAddress = config.getNetconfServerIP();\r
+    }\r
+    List<NetConfServerDetails> result = new ArrayList<>();\r
+\r
+    for (NetConfServerDetailsEntity entity : serverEntities) {\r
+      NetConfServerDetails server = new NetConfServerDetails();\r
+      server.setDeviceId(entity.getDeviceId());\r
+      server.setEnodeBName(entity.getEnodeBName());\r
+      server.setError(NetconfServerManagementError.SUCCESS);\r
+      server.setListenAddress(netconfListenAddress);\r
+      server.setListenPort(entity.getListenPort());\r
+      result.add(server);\r
+    }\r
+    return result;\r
+  }\r
+\r
+  private String getServiceHost() {\r
+    Map<String, String> envs = System.getenv();\r
+    for (Entry<String, String> entry : envs.entrySet()) {\r
+      if (entry.getKey() != null && entry.getKey().endsWith("_NETCONF_SERVICE_SERVICE_HOST")) {\r
+        return entry.getValue();\r
+      }\r
+    }\r
+    return null;\r
+  }\r
+}\r