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