Sonar clean code
[externalapi/nbi.git] / src / main / java / org / onap / nbi / apis / serviceorder / workflow / SOTaskProcessor.java
1 /**
2  * Copyright (c) 2018 Orange
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5  * in compliance with the License. You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software distributed under the License
10  * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11  * or implied. See the License for the specific language governing permissions and limitations under
12  * the License.
13  */
14 package org.onap.nbi.apis.serviceorder.workflow;
15
16 import java.io.IOException;
17 import java.util.ArrayList;
18 import java.util.Arrays;
19 import java.util.Date;
20 import java.util.LinkedHashMap;
21 import java.util.List;
22 import org.onap.nbi.apis.serviceorder.SoClient;
23 import org.onap.nbi.apis.serviceorder.model.ServiceCharacteristic;
24 import org.onap.nbi.apis.serviceorder.model.ServiceOrder;
25 import org.onap.nbi.apis.serviceorder.model.ServiceOrderItem;
26 import org.onap.nbi.apis.serviceorder.model.StateType;
27 import org.onap.nbi.apis.serviceorder.model.consumer.CloudConfiguration;
28 import org.onap.nbi.apis.serviceorder.model.consumer.CreateServiceInstanceResponse;
29 import org.onap.nbi.apis.serviceorder.model.consumer.GetRequestStatusResponse;
30 import org.onap.nbi.apis.serviceorder.model.consumer.ModelInfo;
31 import org.onap.nbi.apis.serviceorder.model.consumer.RequestDetails;
32 import org.onap.nbi.apis.serviceorder.model.consumer.RequestInfo;
33 import org.onap.nbi.apis.serviceorder.model.consumer.RequestParameters;
34 import org.onap.nbi.apis.serviceorder.model.consumer.RequestState;
35 import org.onap.nbi.apis.serviceorder.model.consumer.SubscriberInfo;
36 import org.onap.nbi.apis.serviceorder.model.consumer.UserParams;
37 import org.onap.nbi.apis.serviceorder.model.orchestrator.ExecutionTask;
38 import org.onap.nbi.apis.serviceorder.model.orchestrator.ServiceOrderInfo;
39 import org.onap.nbi.apis.serviceorder.model.orchestrator.ServiceOrderInfoJson;
40 import org.onap.nbi.apis.serviceorder.repositories.ExecutionTaskRepository;
41 import org.onap.nbi.apis.serviceorder.repositories.ServiceOrderRepository;
42 import org.onap.nbi.apis.serviceorder.utils.JsonEntityConverter;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
45 import org.springframework.beans.factory.annotation.Autowired;
46 import org.springframework.beans.factory.annotation.Value;
47 import org.springframework.http.HttpStatus;
48 import org.springframework.http.ResponseEntity;
49 import org.springframework.stereotype.Service;
50 import org.springframework.util.CollectionUtils;
51
52 @Service
53 public class SOTaskProcessor {
54
55     @Value("${nbi.callForVNF}")
56     private boolean enableCallForVNF;
57
58     @Value("${onap.lcpCloudRegionId}")
59     private String lcpCloudRegionId;
60
61     @Value("${onap.tenantId}")
62     private String tenantId;
63
64     @Autowired
65     private ServiceOrderRepository serviceOrderRepository;
66
67     @Autowired
68     private ExecutionTaskRepository executionTaskRepository;
69
70     @Autowired
71     private SoClient soClient;
72
73
74     private static final Logger LOGGER = LoggerFactory.getLogger(SOTaskProcessor.class);
75
76     /**
77      * Run the ServiceOrchestrator processing for a serviceOrderItem which with any sub relations
78      *
79      * @throws InterruptedException
80      */
81     public void processOrderItem(ExecutionTask executionTask) throws InterruptedException {
82
83
84         ServiceOrderInfoJson serviceOrderInfoJson = executionTask.getServiceOrderInfoJson();
85         ServiceOrder serviceOrder = serviceOrderRepository.findOne(serviceOrderInfoJson.getServiceOrderId());
86         ServiceOrderItem serviceOrderItem = null;
87         for (ServiceOrderItem item : serviceOrder.getOrderItem()) {
88             if (item.getId().equals(executionTask.getOrderItemId())) {
89                 serviceOrderItem = item;
90             }
91         }
92
93         ServiceOrderInfo serviceOrderInfo = null;
94         try {
95             serviceOrderInfo =
96                     JsonEntityConverter.convertJsonToServiceOrderInfo(serviceOrderInfoJson.getServiceOrderInfoJson());
97         } catch (IOException e) {
98             LOGGER.warn("Unable to read ServiceOrderInfo Json for serviceOrderId " + serviceOrder.getId(), e);
99         }
100
101         if (serviceOrderItem != null && StateType.ACKNOWLEDGED == serviceOrderItem.getState()) {
102
103             ResponseEntity<CreateServiceInstanceResponse> response = null;
104             try {
105                 response = postSORequest(serviceOrderItem, serviceOrderInfo);
106             } catch (NullPointerException e) {
107                 LOGGER.warn("Enable to create service instance for serviceOrderItem.id=" + serviceOrderItem.getId(), e);
108                 response = null;
109             }
110
111             if (response == null) {
112                 LOGGER.warn("response=null for serviceOrderItem.id=" + serviceOrderItem.getId());
113                 serviceOrderItem.setState(StateType.FAILED);
114             } else {
115                 updateServiceOrderItem(response.getBody(), serviceOrderItem);
116
117                 if (response.getStatusCode() != HttpStatus.CREATED || response.getBody() == null
118                         || response.getBody().getRequestReference() == null) {
119                     serviceOrderItem.setState(StateType.FAILED);
120                 } else {
121                     serviceOrderItem.setState(StateType.INPROGRESS);
122                 }
123             }
124         }
125
126         if (executionTask.getNbRetries() > 0) {
127             // TODO lancer en asynchrone
128             pollSoRequestStatus(serviceOrderItem);
129             if (serviceOrderItem.getState().equals(StateType.COMPLETED)) {
130                 updateSuccessTask(executionTask);
131             } else {
132                 int nbRetries = executionTask.getNbRetries();
133                 executionTask.setNbRetries(--nbRetries);
134                 executionTask.setLastAttemptDate(new Date());
135                 executionTaskRepository.save(executionTask);
136             }
137         } else {
138             updateFailedTask(executionTask, serviceOrder);
139         }
140
141
142         updateServiceOrder(serviceOrder);
143     }
144
145     private ResponseEntity<CreateServiceInstanceResponse> postSORequest(ServiceOrderItem serviceOrderItem,
146             ServiceOrderInfo serviceOrderInfo) {
147         RequestDetails requestDetails = buildSoRequest(serviceOrderItem,
148                 serviceOrderInfo.getServiceOrderItemInfos().get(serviceOrderItem.getId()).getCatalogResponse(),
149                 serviceOrderInfo.getSubscriberInfo());
150         ResponseEntity<CreateServiceInstanceResponse> response = null;
151
152         switch (serviceOrderItem.getAction()) {
153             case ADD:
154                 response = soClient.callCreateServiceInstance(requestDetails);
155                 break;
156             case DELETE:
157                 response = soClient.callDeleteServiceInstance(requestDetails, serviceOrderItem.getService().getId());
158                 break;
159             default:
160                 break;
161         }
162         return response;
163     }
164
165     private void updateServiceOrder(ServiceOrder serviceOrder) {
166         boolean atLeastOneCompleted = false;
167         boolean atLeastOneNotFinished = false;
168         boolean atLeastOneFailed = false;
169
170
171         for (ServiceOrderItem serviceOrderItem : serviceOrder.getOrderItem()) {
172             switch (serviceOrderItem.getState()) {
173                 case COMPLETED:
174                     atLeastOneCompleted = true;
175                     break;
176                 case INPROGRESS:
177                 case ACKNOWLEDGED:
178                     atLeastOneNotFinished = true;
179                     break;
180                 case FAILED:
181                     atLeastOneFailed = true;
182                     break;
183                 default:
184                     break;
185
186             }
187         }
188
189         if (atLeastOneNotFinished) {
190             serviceOrder.setState(StateType.INPROGRESS);
191         } else {
192             serviceOrder.setCompletionDateTime(new Date());
193             if (atLeastOneFailed) {
194                 if (!atLeastOneCompleted) {
195                     serviceOrder.setState(StateType.FAILED);
196                 } else {
197                     serviceOrder.setState(StateType.PARTIAL);
198                 }
199             } else {
200                 serviceOrder.setState(StateType.COMPLETED);
201             }
202         }
203         serviceOrderRepository.save(serviceOrder);
204     }
205
206
207     /**
208      * * @param orderItem
209      *
210      * @throws InterruptedException
211      */
212     private void pollSoRequestStatus(ServiceOrderItem orderItem) throws InterruptedException {
213         boolean stopPolling = false;
214         String requestId = orderItem.getRequestId();
215         GetRequestStatusResponse response = null;
216         int nbRetries = 0;
217
218         while (!stopPolling) {
219             response = soClient.callGetRequestStatus(requestId);
220             if (response != null) {
221                 if (response.getRequest().getRequestStatus().getPercentProgress() != 100) {
222                     nbRetries++;
223                     orderItem.setState(StateType.INPROGRESS);
224                     Thread.sleep(1000);
225                 } else if (RequestState.COMPLETE != response.getRequest().getRequestStatus().getRequestState()) {
226                     orderItem.setState(StateType.FAILED);
227                     stopPolling = true;
228                 } else {
229                     orderItem.setState(StateType.COMPLETED);
230                     stopPolling = true;
231                 }
232             } else {
233                 orderItem.setState(StateType.INPROGRESS);
234                 stopPolling = true;
235             }
236             if (nbRetries == 3) {
237                 stopPolling = true;
238             }
239         }
240     }
241
242     /**
243      * Build SO CREATE request from the ServiceOrder and catalog informations from SDC
244      *
245      * @param orderItem
246      * @param sdcInfos
247      * @param subscriberInfo
248      * @return
249      */
250     private RequestDetails buildSoRequest(ServiceOrderItem orderItem, LinkedHashMap<String, Object> sdcInfos,
251             SubscriberInfo subscriberInfo) {
252         RequestDetails requestDetails = new RequestDetails();
253
254         requestDetails.setSubscriberInfo(subscriberInfo);
255
256         ModelInfo modelInfo = new ModelInfo();
257         modelInfo.setModelType("service");
258         modelInfo.setModelInvariantId((String) sdcInfos.get("invariantUUID"));
259         modelInfo.setModelNameVersionId(orderItem.getService().getServiceSpecification().getId());
260         modelInfo.setModelName((String) sdcInfos.get("name"));
261         modelInfo.setModelVersion((String) sdcInfos.get("version"));
262         requestDetails.setModelInfo(modelInfo);
263
264         RequestInfo requestInfo = new RequestInfo();
265         requestInfo.setInstanceName(orderItem.getService().getName());
266         requestInfo.setSource("VID");
267         requestInfo.setSuppressRollback(false);
268         requestDetails.setRequestInfo(requestInfo);
269
270         RequestParameters requestParameters = new RequestParameters();
271         requestParameters.setSubscriptionServiceType((String) sdcInfos.get("name"));
272         requestParameters.setUserParams(
273                 retrieveUserParamsFromServiceCharacteristics(orderItem.getService().getServiceCharacteristic()));
274         requestParameters.setaLaCarte(true);
275         requestDetails.setRequestParameters(requestParameters);
276
277         CloudConfiguration cloudConfiguration = new CloudConfiguration(lcpCloudRegionId, tenantId);
278         requestDetails.setCloudConfiguration(cloudConfiguration);
279         return requestDetails;
280     }
281
282     /**
283      * Build a list of UserParams for the SO request by browsing a list of ServiceCharacteristics from
284      * SDC
285      *
286      * @param characteristics
287      * @return
288      */
289     private List<UserParams> retrieveUserParamsFromServiceCharacteristics(List<ServiceCharacteristic> characteristics) {
290         List<UserParams> userParams = new ArrayList<UserParams>();
291
292         if (!CollectionUtils.isEmpty(characteristics)) {
293             for (ServiceCharacteristic characteristic : characteristics) {
294                 UserParams userParam = new UserParams(characteristic.getName(),
295                         characteristic.getValue().getServiceCharacteristicValue());
296                 userParams.add(userParam);
297             }
298         }
299
300         return userParams;
301     }
302
303
304     /**
305      * Update ServiceOrderItem with SO response by using serviceOrderRepository with the serviceOrderId
306      *
307      * @param createServiceInstanceResponse
308      * @param orderItem
309      */
310     private void updateServiceOrderItem(CreateServiceInstanceResponse createServiceInstanceResponse,
311             ServiceOrderItem orderItem) {
312
313         if (createServiceInstanceResponse != null && !orderItem.getState().equals(StateType.FAILED)) {
314             orderItem.getService().setId(createServiceInstanceResponse.getRequestReference().getInstanceId());
315             orderItem.setRequestId(createServiceInstanceResponse.getRequestReference().getRequestId());
316         }
317     }
318
319     /**
320      * Update an executionTask in database when it's process with a success
321      *
322      * @param executionTask
323      */
324     private void updateSuccessTask(ExecutionTask executionTask) {
325         executionTaskRepository.delete(executionTask.getInternalId());
326         executionTaskRepository.updateReliedTaskAfterDelete(executionTask.getInternalId());
327     }
328
329     /**
330      * @param executionTask
331      * @param serviceOrder
332      */
333     private void updateFailedTask(ExecutionTask executionTask, ServiceOrder serviceOrder) {
334         List<ExecutionTask> executionTasksToDelete = findExecutionTasksRecursively(executionTask);
335         for (ExecutionTask taskId : executionTasksToDelete) {
336             executionTaskRepository.delete(taskId);
337         }
338
339         for (ServiceOrderItem item : serviceOrder.getOrderItem()) {
340             for (ExecutionTask taskToDelete : executionTasksToDelete) {
341                 if (taskToDelete.getOrderItemId().equals(item.getId())) {
342                     item.setState(StateType.FAILED);
343                 }
344             }
345         }
346     }
347
348     /**
349      * @param executionTask
350      * @return
351      */
352     private List<ExecutionTask> findExecutionTasksRecursively(ExecutionTask executionTask) {
353
354         List<ExecutionTask> executionTasks = new ArrayList<>();
355
356         List<ExecutionTask> tasksReliedToAnOrderItemId =
357                 executionTaskRepository.findTasksReliedToAnOrderItemId(executionTask.getInternalId());
358
359         if (CollectionUtils.isEmpty(tasksReliedToAnOrderItemId)) {
360             return Arrays.asList(executionTask);
361         } else {
362             for (ExecutionTask task : tasksReliedToAnOrderItemId) {
363                 executionTasks.addAll(findExecutionTasksRecursively(task));
364             }
365         }
366         executionTasks.add(executionTask);
367         return executionTasks;
368     }
369
370
371 }