Initial source code
[oam/tr069-adapter.git] / netconf-server / src / main / java / org / commscope / tr069adapter / netconf / server / NetConfServerManagerImpl.java
1 /*\r
2  * ============LICENSE_START========================================================================\r
3  * ONAP : tr-069-adapter\r
4  * =================================================================================================\r
5  * Copyright (C) 2020 CommScope Inc Intellectual Property.\r
6  * =================================================================================================\r
7  * This tr-069-adapter software file is distributed by CommScope Inc under the Apache License,\r
8  * Version 2.0 (the "License"); you may not use this file except in compliance with the License. You\r
9  * may obtain a copy of the License at\r
10  *\r
11  * http://www.apache.org/licenses/LICENSE-2.0\r
12  *\r
13  * This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,\r
14  * either express or implied. See the License for the specific language governing permissions and\r
15  * limitations under the License.\r
16  * ===============LICENSE_END=======================================================================\r
17  */\r
18 \r
19 package org.commscope.tr069adapter.netconf.server;\r
20 \r
21 import java.net.URI;\r
22 import java.net.URISyntaxException;\r
23 import java.util.ArrayList;\r
24 import java.util.List;\r
25 import java.util.Map;\r
26 import java.util.Map.Entry;\r
27 \r
28 import org.commscope.tr069adapter.mapper.model.NetConfServerDetails;\r
29 import org.commscope.tr069adapter.mapper.model.NetconfServerManagementError;\r
30 import org.commscope.tr069adapter.netconf.config.NetConfServerProperties;\r
31 import org.commscope.tr069adapter.netconf.dao.NetConfServerDetailsRepository;\r
32 import org.commscope.tr069adapter.netconf.entity.NetConfServerDetailsEntity;\r
33 import org.commscope.tr069adapter.netconf.error.RetryFailedException;\r
34 import org.commscope.tr069adapter.netconf.error.ServerPortAllocationException;\r
35 import org.commscope.tr069adapter.netconf.server.helper.ServerPortAllocationHelper;\r
36 import org.slf4j.Logger;\r
37 import org.slf4j.LoggerFactory;\r
38 import org.springframework.beans.factory.annotation.Autowired;\r
39 import org.springframework.http.HttpEntity;\r
40 import org.springframework.http.HttpHeaders;\r
41 import org.springframework.stereotype.Component;\r
42 import org.springframework.web.client.RestTemplate;\r
43 \r
44 @Component\r
45 public class NetConfServerManagerImpl {\r
46 \r
47   private static final Logger LOG = LoggerFactory.getLogger(NetConfServerManagerImpl.class);\r
48 \r
49   @Autowired\r
50   ServerPortAllocationHelper serverPortAllocator;\r
51 \r
52   @Autowired\r
53   NetConfServerDetailsRepository netconfDAO;\r
54 \r
55   @Autowired\r
56   NetConfServerProperties config;\r
57 \r
58   @Autowired\r
59   NetconfServerStarter ncServerStarter;\r
60 \r
61   @Autowired\r
62   RestartNetconfServerHandler restartServersHandler;\r
63 \r
64   public void restartServers() {\r
65     LOG.debug("Restarting all netconf servers during startup...");\r
66     Iterable<NetConfServerDetailsEntity> entities = netconfDAO.findAll();\r
67     List<NetConfServerDetailsEntity> serverDetailsList = new ArrayList<>();\r
68     for (NetConfServerDetailsEntity entity : entities) {\r
69       serverDetailsList.add(entity);\r
70     }\r
71     restartServersOnStartup(serverDetailsList);\r
72 \r
73     if (!serverDetailsList.isEmpty()) {\r
74       LOG.debug("Attempting to start failed netconf servers {}", serverDetailsList);\r
75       try {\r
76         restartServersHandler.restart(serverDetailsList);\r
77       } catch (RetryFailedException e) {\r
78         LOG.error("Failed to restart all netconf servers. {}", e.toString());\r
79       }\r
80     }\r
81     LOG.debug("Restarting netconf servers during startup is completed.");\r
82   }\r
83 \r
84   public NetConfServerDetails createServer(String deviceId, String enodeBName) {\r
85     NetConfServerDetails result = new NetConfServerDetails();\r
86     NetConfServerDetailsEntity entity = null;\r
87     if (deviceId != null) {\r
88       entity = netconfDAO.findByDeviceId(deviceId);\r
89     } else if (enodeBName != null) {\r
90       entity = netconfDAO.findByEnodeBName(enodeBName);\r
91     } else {\r
92       // none is specified\r
93       LOG.error(\r
94           "Both deviceID and enodeBName are null. Hence failed to create the netconf server.");\r
95       return null;\r
96     }\r
97 \r
98     if (null != entity) {\r
99       // found the entity. server is already running. double check and run\r
100       // if\r
101       // required. else return the details.\r
102 \r
103       // update the ENB Name if Changed\r
104       entity.setEnodeBName(enodeBName);\r
105       netconfDAO.save(entity);\r
106       result = getNetConfServerDetails(deviceId, entity);\r
107       return result;\r
108     }\r
109 \r
110     try {\r
111 \r
112       String port = serverPortAllocator.reserveServerPort();\r
113       LOG.debug("Successfully reserved a port for deviceID={} ,port={}", deviceId, port);\r
114 \r
115       // start the server\r
116       boolean isServerStarted = ncServerStarter.startServer(port, deviceId);\r
117       boolean isPortInUse = serverPortAllocator.isServerPortInUse(port);\r
118 \r
119       if (!isServerStarted || !isPortInUse) {\r
120         LOG.error(\r
121             "Failed to start netconf server for deviceID: {}, at port:{} , isServerStarted={} ,isPortInUse={}",\r
122             deviceId, port, isServerStarted, isPortInUse);\r
123         return null;\r
124       }\r
125 \r
126       // save the record in db\r
127       entity = new NetConfServerDetailsEntity();\r
128       entity.setDeviceId(deviceId);\r
129       entity.setListenPort(port);\r
130       entity.setEnodeBName(enodeBName);\r
131       netconfDAO.save(entity);\r
132 \r
133       result = getNetConfServerDetails(deviceId, entity);\r
134       LOG.debug("Successfully started netconf server for deviceID= {}, port={}", deviceId, port);\r
135 \r
136     } catch (ServerPortAllocationException e) {\r
137       LOG.error("Failed to allocate a port {}", e.toString());\r
138     }\r
139 \r
140     if (entity != null) {\r
141       result.setDeviceId(deviceId);\r
142       result.setListenPort(entity.getListenPort());\r
143       String netconfListenAddress = getServiceHost();\r
144       if (netconfListenAddress == null) {\r
145         netconfListenAddress = config.getNetconfServerIP();\r
146       }\r
147       result.setListenAddress(netconfListenAddress);\r
148       result.setError(NetconfServerManagementError.SUCCESS);\r
149     }\r
150     return result;\r
151   }\r
152 \r
153   public void restartServersOnStartup(List<NetConfServerDetailsEntity> serverDetailsList) {\r
154 \r
155     List<NetConfServerDetailsEntity> startedServers = new ArrayList<>();\r
156     for (NetConfServerDetailsEntity entity : serverDetailsList) {\r
157 \r
158       serverPortAllocator.checkAndReserveServerPort(entity.getListenPort());\r
159 \r
160       serverPortAllocator.isServerPortInUse(entity.getListenPort());\r
161       boolean isServerStarted =\r
162           ncServerStarter.startServer(entity.getListenPort(), entity.getDeviceId());\r
163 \r
164       if (isServerStarted) {\r
165         LOG.info("Successfully restarted NETCONF server {}  on port {}  upon application startup.",\r
166             entity.getDeviceId(), entity.getListenPort());\r
167         // we need to push the pnfEntry for IP updated\r
168         NetConfServerDetails details = getNetConfServerDetails(entity.getDeviceId(), entity);\r
169 \r
170         final String baseUrl = config.getMapperPath() + "/registerNetconfServer";\r
171         URI uri = null;\r
172         try {\r
173           uri = new URI(baseUrl);\r
174         } catch (URISyntaxException e) {\r
175           LOG.error("error while contructing the URI {}", e.toString());\r
176         }\r
177         RestTemplate restTemplate = new RestTemplate();\r
178         HttpHeaders headers = new HttpHeaders();\r
179         HttpEntity<NetConfServerDetails> httpentity = new HttpEntity<>(details, headers);\r
180         boolean isSuccess = false;\r
181         if (uri != null) {\r
182           isSuccess = restTemplate.postForObject(uri, httpentity, Boolean.class);\r
183         }\r
184 \r
185         if (!isSuccess) {\r
186           LOG.error("Netconf Register request is failed update the updated host details..");\r
187         } else {\r
188           LOG.debug("successfully started the server");\r
189         }\r
190         startedServers.add(entity);\r
191       } else {\r
192         LOG.error("Failed to restart NETCONF server {}  on port {}  upon application startup.",\r
193             entity.getDeviceId(), entity.getListenPort());\r
194       }\r
195     }\r
196     if (!serverDetailsList.isEmpty()) {\r
197       serverDetailsList.removeAll(startedServers);\r
198     }\r
199   }\r
200 \r
201   private NetConfServerDetails getNetConfServerDetails(String deviceId,\r
202       NetConfServerDetailsEntity entity) {\r
203     NetConfServerDetails result = new NetConfServerDetails();\r
204     result.setDeviceId(deviceId);\r
205     result.setListenPort(entity.getListenPort());\r
206     result.setEnodeBName(entity.getEnodeBName());\r
207     String netconfListenAddress = getServiceHost();\r
208     if (netconfListenAddress == null) {\r
209       netconfListenAddress = config.getNetconfServerIP();\r
210     }\r
211     result.setListenAddress(netconfListenAddress);\r
212     result.setError(NetconfServerManagementError.SUCCESS);\r
213     return result;\r
214   }\r
215 \r
216   public boolean unregister(String deviceId, String enodeBName) {\r
217     LOG.debug("Unregister is not yet supported deviceId={} enodeBName={}", deviceId, enodeBName);\r
218     return false;\r
219   }\r
220 \r
221   public List<NetConfServerDetails> getServersInfo() {\r
222     Iterable<NetConfServerDetailsEntity> serverEntities = netconfDAO.findAll();\r
223     String netconfListenAddress = getServiceHost();\r
224     if (netconfListenAddress == null) {\r
225       netconfListenAddress = config.getNetconfServerIP();\r
226     }\r
227     List<NetConfServerDetails> result = new ArrayList<>();\r
228 \r
229     for (NetConfServerDetailsEntity entity : serverEntities) {\r
230       NetConfServerDetails server = new NetConfServerDetails();\r
231       server.setDeviceId(entity.getDeviceId());\r
232       server.setEnodeBName(entity.getEnodeBName());\r
233       server.setError(NetconfServerManagementError.SUCCESS);\r
234       server.setListenAddress(netconfListenAddress);\r
235       server.setListenPort(entity.getListenPort());\r
236       result.add(server);\r
237     }\r
238     return result;\r
239   }\r
240 \r
241   private String getServiceHost() {\r
242     Map<String, String> envs = System.getenv();\r
243     for (Entry<String, String> entry : envs.entrySet()) {\r
244       if (entry.getKey() != null && entry.getKey().endsWith("_NETCONF_SERVICE_SERVICE_HOST")) {\r
245         return entry.getValue();\r
246       }\r
247     }\r
248     return null;\r
249   }\r
250 }\r