--- /dev/null
+/*\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