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