a3a1fd54b2c492497dbb1fe202510480db8b80d7
[oam/tr069-adapter.git] / mapper / src / main / java / org / commscope / tr069adapter / mapper / acs / impl / PnPPreProvisioningHandler.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.mapper.acs.impl;\r
20 \r
21 import java.util.ArrayList;\r
22 import java.util.Iterator;\r
23 import java.util.List;\r
24 import java.util.Map;\r
25 import org.commscope.tr069adapter.acs.common.DeviceInform;\r
26 import org.commscope.tr069adapter.acs.common.DeviceRPCRequest;\r
27 import org.commscope.tr069adapter.acs.common.DeviceRPCResponse;\r
28 import org.commscope.tr069adapter.acs.common.ParameterDTO;\r
29 import org.commscope.tr069adapter.acs.common.dto.ConfigurationData;\r
30 import org.commscope.tr069adapter.acs.common.dto.TR069OperationCode;\r
31 import org.commscope.tr069adapter.acs.common.dto.TR069OperationDetails;\r
32 import org.commscope.tr069adapter.acs.common.inform.BootInform;\r
33 import org.commscope.tr069adapter.acs.common.inform.BootstrapInform;\r
34 import org.commscope.tr069adapter.mapper.MOMetaData;\r
35 import org.commscope.tr069adapter.mapper.MapperConfigProperties;\r
36 import org.commscope.tr069adapter.mapper.sync.SynchronizedRequestHandler;\r
37 import org.commscope.tr069adapter.mapper.util.MOMetaDataUtil;\r
38 import org.commscope.tr069adapter.mapper.util.NetconfToTr069MapperUtil;\r
39 import org.slf4j.Logger;\r
40 import org.slf4j.LoggerFactory;\r
41 import org.slf4j.MDC;\r
42 import org.springframework.beans.factory.annotation.Autowired;\r
43 import org.springframework.http.HttpEntity;\r
44 import org.springframework.http.HttpHeaders;\r
45 import org.springframework.http.MediaType;\r
46 import org.springframework.http.ResponseEntity;\r
47 import org.springframework.stereotype.Component;\r
48 import org.springframework.util.LinkedMultiValueMap;\r
49 import org.springframework.util.MultiValueMap;\r
50 import org.springframework.util.StringUtils;\r
51 import org.springframework.web.client.RestTemplate;\r
52 \r
53 @Component\r
54 public class PnPPreProvisioningHandler {\r
55 \r
56   private static final Logger logger = LoggerFactory.getLogger(PnPPreProvisioningHandler.class);\r
57 \r
58   private static String clientString = "client";\r
59   private static final String ADMIN_STATE = "AdminState";\r
60   private static final String ENODEB_NAME = "X_0005B9_eNBName";\r
61 \r
62   @Autowired\r
63   SynchronizedRequestHandler syncHandler;\r
64 \r
65   @Autowired\r
66   MOMetaDataUtil moMetaDataUtil;\r
67 \r
68   @Autowired\r
69   MapperConfigProperties config;\r
70 \r
71   private RestTemplate restTemplate = new RestTemplate();\r
72 \r
73   /**\r
74    * @param notification\r
75    */\r
76   public void onDeviceNotification(DeviceInform notification) {\r
77     String deviceId = null;\r
78     try {\r
79       if (notification instanceof BootstrapInform || notification instanceof BootInform) {\r
80         logger.debug("Checking whether the PnP pre-configuration is enabled");\r
81         if (isPreConfigureOnPnPEnabled()) {\r
82           logger.info(\r
83               "Pre-configuration during Bootstrap or Boot is enabled, hence the configuration imported in Config DB shall be provisioned to the device");\r
84         } else {\r
85           logger.debug("Pre-configuration on PnP is disabled!!!");\r
86           return;\r
87         }\r
88       }\r
89 \r
90       if (notification instanceof BootstrapInform) {\r
91         BootstrapInform bootstrapNotification = (BootstrapInform) notification;\r
92         deviceId = bootstrapNotification.getDeviceDetails().getDeviceId();\r
93         MDC.put(clientString, deviceId);\r
94         logger.info("Bootstrap notification received");\r
95         performPreProvisioning(deviceId,\r
96             bootstrapNotification.getDeviceDetails().getSoftwareVersion(),\r
97             bootstrapNotification.getDeviceDetails().getHardwareVersion(), false);\r
98 \r
99       } else if (notification instanceof BootInform) {\r
100         BootInform bootNotification = (BootInform) notification;\r
101         deviceId = bootNotification.getDeviceDetails().getDeviceId();\r
102         MDC.put(clientString, deviceId);\r
103         logger.info("Boot notification received");\r
104 \r
105         performPreProvisioning(deviceId, bootNotification.getDeviceDetails().getSoftwareVersion(),\r
106             bootNotification.getDeviceDetails().getHardwareVersion(), true);\r
107       }\r
108 \r
109       logger.debug("Successfully completed provisioning of PnP mandatory parameters");\r
110     } finally {\r
111       MDC.remove(clientString);\r
112     }\r
113   }\r
114 \r
115   /**\r
116    * @param deviceId\r
117    * @param isBoot\r
118    */\r
119   private void performPreProvisioning(String deviceId, String swVersion, String hwVersion,\r
120       boolean isBoot) {\r
121     List<DeviceRPCRequest> deviceRPCRequestList =\r
122         prepareNBIDeviceOperationrequest(deviceId, swVersion, hwVersion, isBoot);\r
123     if (deviceRPCRequestList.isEmpty()) {\r
124       logger.debug("No Operation requests exists to perform pre provision on the device");\r
125       return;\r
126     }\r
127 \r
128     boolean isMandatoryProvFailed = false;\r
129     for (DeviceRPCRequest deviceRPCRequest : deviceRPCRequestList) {\r
130       logger.info("Performing PROVISION operation");\r
131       DeviceRPCResponse deviceRPCResponse = syncHandler.performDeviceOperation(deviceRPCRequest);\r
132       logger.debug("Received Provisioning Operation result");\r
133       if (deviceRPCResponse != null && !StringUtils.isEmpty(deviceRPCResponse.getFaultString())) {\r
134         logger.error("Device operation failed, Reason: {}", deviceRPCResponse.getFaultString());\r
135         isMandatoryProvFailed = true;\r
136         break;\r
137       }\r
138 \r
139       logger.debug("Provisioning is successful");\r
140     }\r
141 \r
142     if (isMandatoryProvFailed) {\r
143       logger\r
144           .debug("Mandatory provisioning has failed, hence provisioning Admin down on the device");\r
145       provisionAdminDown(deviceRPCRequestList);\r
146       logger.debug("AdminDown Provisioning is successful");\r
147     }\r
148   }\r
149 \r
150   private void provisionAdminDown(List<DeviceRPCRequest> deviceRPCRequestList) {\r
151     DeviceRPCRequest adminDownOpRequest = null;\r
152     for (DeviceRPCRequest nbiDeviceOperationRequest : deviceRPCRequestList) {\r
153       ParameterDTO param = nbiDeviceOperationRequest.getOpDetails().getParmeters().get(0);\r
154       if (param.getParamName().endsWith(ADMIN_STATE)) {\r
155         adminDownOpRequest = nbiDeviceOperationRequest;\r
156         break;\r
157       }\r
158     }\r
159     if (adminDownOpRequest != null) {\r
160       List<ParameterDTO> adminDownParams = adminDownOpRequest.getOpDetails().getParmeters();\r
161       for (ParameterDTO adminDownParam : adminDownParams) {\r
162         adminDownParam.setParamValue("0");\r
163       }\r
164       DeviceRPCResponse deviceRPCResponse = syncHandler.performDeviceOperation(adminDownOpRequest);\r
165       if (deviceRPCResponse == null || !StringUtils.isEmpty(deviceRPCResponse.getFaultString())) {\r
166         logger.error("Device operation failed, Reason: {}", ((deviceRPCResponse == null)\r
167             ? "Null Operation result" : deviceRPCResponse.getFaultString()));\r
168       }\r
169     }\r
170   }\r
171 \r
172   /**\r
173    * @param deviceId\r
174    * @param isBoot\r
175    * @return\r
176    */\r
177   private List<DeviceRPCRequest> prepareNBIDeviceOperationrequest(String deviceId, String swVersion,\r
178       String hwVersion, boolean isBoot) {\r
179     logger.debug("Preparing the NBI Device Operation Request");\r
180     List<DeviceRPCRequest> deviceRPCRequestList = new ArrayList<>();\r
181 \r
182     ConfigurationData configData = getDeviceConfigurationData(deviceId, swVersion, hwVersion);\r
183     if (configData == null || configData.getParameterMONameValueMap().isEmpty()) {\r
184       logger.debug("No configuration exists for the device");\r
185       return deviceRPCRequestList;\r
186     }\r
187 \r
188     List<ParameterDTO> configParams = new ArrayList<>();\r
189     List<ParameterDTO> adminStateParams = new ArrayList<>();\r
190     Map<String, String> paramNameValueMap = configData.getParameterMONameValueMap();\r
191     Iterator<String> iter = paramNameValueMap.keySet().iterator();\r
192     while (iter.hasNext()) {\r
193       String paramName = iter.next();\r
194       String paramValue = paramNameValueMap.get(paramName);\r
195       MOMetaData moMetaData = moMetaDataUtil.getMetaDataByTR69Name(paramName, swVersion, hwVersion);\r
196       if ((isBoot && !paramName.endsWith(ADMIN_STATE)) || moMetaData == null)\r
197         continue;\r
198       ParameterDTO parameterDTO = getParameterDTO(paramName, paramValue, moMetaData);\r
199 \r
200       if (paramName.endsWith(ADMIN_STATE)) {\r
201         adminStateParams.add(parameterDTO);\r
202       } else {\r
203         configParams.add(parameterDTO);\r
204       }\r
205       logger.debug("Param -> {} Param Value: {}", paramName, paramValue);\r
206     }\r
207 \r
208     if (configParams.isEmpty() && adminStateParams.isEmpty()) {\r
209       logger.debug("Empty parameters list from config db, hence not performing pre-provision");\r
210       return deviceRPCRequestList;\r
211     }\r
212 \r
213     if (!configParams.isEmpty()) {\r
214       deviceRPCRequestList.add(createNBIOperationRequest(deviceId, configParams));\r
215     }\r
216 \r
217     if (!adminStateParams.isEmpty()) {\r
218       deviceRPCRequestList.add(createNBIOperationRequest(deviceId, adminStateParams));\r
219     }\r
220 \r
221     return deviceRPCRequestList;\r
222   }\r
223 \r
224   private ParameterDTO getParameterDTO(String paramName, String paramValue, MOMetaData moMetaData) {\r
225     String dataType = moMetaData.getDataType();\r
226     if (dataType.equals("boolean")) {\r
227       if (paramValue.equalsIgnoreCase("true")) {\r
228         paramValue = "1";\r
229       } else if (paramValue.equalsIgnoreCase("false")) {\r
230         paramValue = "0";\r
231       }\r
232     }\r
233     ParameterDTO parameterDTO = new ParameterDTO(paramName, paramValue);\r
234     parameterDTO.setDataType(dataType);\r
235 \r
236     return parameterDTO;\r
237   }\r
238 \r
239   /**\r
240    * @param deviceId\r
241    * @param params\r
242    * @return\r
243    */\r
244   private DeviceRPCRequest createNBIOperationRequest(String deviceId, List<ParameterDTO> params) {\r
245     TR069OperationDetails opDetails = new TR069OperationDetails();\r
246     opDetails.setOpCode(TR069OperationCode.SET_PARAMETER_VALUES);\r
247 \r
248     return NetconfToTr069MapperUtil.handleParamsOperation(params, opDetails, deviceId);\r
249 \r
250   }\r
251 \r
252   /**\r
253    * @param deviceId\r
254    * @return\r
255    */\r
256   private ConfigurationData getDeviceConfigurationData(String deviceId, String swVersion,\r
257       String hwVersion) {\r
258     String configDBURI = getConfigDBURI();\r
259     logger.debug(\r
260         "Device Configuration to be fetched from Config DB URI: {}, macId {}, swVersion {}, hwVersion {}",\r
261         configDBURI, deviceId, swVersion, hwVersion);\r
262     ConfigurationData configData = null;\r
263     try {\r
264 \r
265       MultiValueMap<String, String> uriParams = new LinkedMultiValueMap<>();\r
266       uriParams.add("macId", deviceId);\r
267       uriParams.add("swVersion", swVersion);\r
268       uriParams.add("hwVersion", hwVersion);\r
269       HttpHeaders headers = new HttpHeaders();\r
270       headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);\r
271       final HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(uriParams, headers);\r
272 \r
273       ResponseEntity<ConfigurationData> res =\r
274           restTemplate.postForEntity(configDBURI, entity, ConfigurationData.class);\r
275       configData = res.getBody();\r
276       logger.debug("Successfully retrived config data for device id{} data {}", deviceId,\r
277           configData);\r
278     } catch (Exception e) {\r
279       logger.error("An exception occurred to get the initial device configuration, Reason: {}",\r
280           e.getMessage());\r
281     }\r
282     return configData;\r
283   }\r
284 \r
285   /**\r
286    * @return\r
287    */\r
288   private boolean isPreConfigureOnPnPEnabled() {\r
289     boolean isEnabled = false;\r
290     String preConfigureOnPnP = config.getPreConfigureOnPNP();\r
291     if (preConfigureOnPnP != null && ("true".equalsIgnoreCase(preConfigureOnPnP)\r
292         || "false".equalsIgnoreCase(preConfigureOnPnP))) {\r
293       isEnabled = Boolean.valueOf(preConfigureOnPnP);\r
294     }\r
295 \r
296     return isEnabled;\r
297   }\r
298 \r
299   /**\r
300    * @return\r
301    */\r
302   private String getConfigDBURI() {\r
303     return config.getConfigDBUri();\r
304 \r
305   }\r
306 \r
307   /**\r
308    * it will return the eNodBName if the configuration is imported\r
309    * \r
310    * @return String\r
311    */\r
312   public String getEnodeBName(String deviceId, String swVersion, String hwVersion) {\r
313     String eNodeBName = null;\r
314     if (isPreConfigureOnPnPEnabled()) {\r
315       ConfigurationData configData = getDeviceConfigurationData(deviceId, swVersion, hwVersion);\r
316       if (configData == null || configData.getParameterMONameValueMap().isEmpty()) {\r
317         logger.debug("No configuration exists for the device");\r
318         return eNodeBName;\r
319       }\r
320 \r
321       Map<String, String> paramNameValueMap = configData.getParameterMONameValueMap();\r
322       Iterator<String> iter = paramNameValueMap.keySet().iterator();\r
323       while (iter.hasNext()) {\r
324         String paramName = iter.next();\r
325         if (paramName.endsWith(ENODEB_NAME)) {\r
326           eNodeBName = paramNameValueMap.get(paramName);\r
327           break;\r
328         }\r
329       }\r
330     }\r
331     return eNodeBName;\r
332   }\r
333 }\r