2 * Copyright (c) 2018 Orange
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 * the License. You may obtain a copy of the License at
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 * specific language governing permissions and limitations under the License.
14 package org.onap.nbi.apis.serviceorder.workflow;
16 import java.io.IOException;
17 import java.util.ArrayList;
18 import java.util.Arrays;
19 import java.util.Date;
20 import java.util.List;
21 import java.util.Optional;
22 import org.onap.nbi.apis.serviceorder.model.ActionType;
23 import org.onap.nbi.apis.serviceorder.model.ServiceOrder;
24 import org.onap.nbi.apis.serviceorder.model.ServiceOrderItem;
25 import org.onap.nbi.apis.serviceorder.model.StateType;
26 import org.onap.nbi.apis.serviceorder.model.consumer.CreateE2EServiceInstanceResponse;
27 import org.onap.nbi.apis.serviceorder.model.consumer.CreateMacroServiceInstanceResponse;
28 import org.onap.nbi.apis.serviceorder.model.consumer.CreateServiceInstanceResponse;
29 import org.onap.nbi.apis.serviceorder.model.orchestrator.ExecutionTask;
30 import org.onap.nbi.apis.serviceorder.model.orchestrator.ServiceOrderInfo;
31 import org.onap.nbi.apis.serviceorder.repositories.ExecutionTaskRepository;
32 import org.onap.nbi.apis.serviceorder.service.ServiceOrderService;
33 import org.onap.nbi.apis.serviceorder.utils.E2EServiceUtils;
34 import org.onap.nbi.apis.serviceorder.utils.JsonEntityConverter;
35 import org.onap.nbi.apis.serviceorder.utils.MacroServiceUtils;
36 import org.onap.nbi.exceptions.TechnicalException;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
39 import org.springframework.beans.factory.annotation.Autowired;
40 import org.springframework.beans.factory.annotation.Value;
41 import org.springframework.http.HttpStatus;
42 import org.springframework.http.ResponseEntity;
43 import org.springframework.stereotype.Service;
44 import org.springframework.util.CollectionUtils;
47 public class SOTaskProcessor {
50 private ServiceOrderService serviceOrderService;
53 private ExecutionTaskRepository executionTaskRepository;
56 private PostSoProcessor postSoProcessor;
59 private SOGetStatusManager sOGetStatusManager;
61 @Value("${scheduler.pollingDurationInMins}")
62 private float pollingDurationInMins;
64 private static final Logger LOGGER = LoggerFactory.getLogger(SOTaskProcessor.class);
67 * Run the ServiceOrchestrator processing for a serviceOrderItem which with any sub relations
69 public void processOrderItem(ExecutionTask executionTask) {
71 executionTask.setLastAttemptDate(new Date());
72 executionTaskRepository.save(executionTask);
74 ServiceOrderInfo serviceOrderInfo = getServiceOrderInfo(executionTask);
76 Optional<ServiceOrder> optionalServiceOrder =
77 serviceOrderService.findServiceOrderById(serviceOrderInfo.getServiceOrderId());
78 if (!optionalServiceOrder.isPresent()) {
79 throw new TechnicalException(
80 "Unable to retrieve service order for id " + serviceOrderInfo.getServiceOrderId());
82 ServiceOrder serviceOrder = optionalServiceOrder.get();
83 ServiceOrderItem serviceOrderItem = getServiceOrderItem(executionTask, serviceOrder);
85 E2EServiceUtils.isE2EService(serviceOrderInfo.getServiceOrderItemInfos().get(serviceOrderItem.getId()));
86 boolean macroService = MacroServiceUtils
87 .isMacroService(serviceOrderInfo.getServiceOrderItemInfos().get(serviceOrderItem.getId()));
89 if (shouldPostSo(serviceOrderItem)) {
91 ResponseEntity<CreateE2EServiceInstanceResponse> response =
92 postSoProcessor.postE2EServiceOrderItem(serviceOrderInfo, serviceOrderItem, serviceOrder);
93 updateE2EServiceOrderItem(response, serviceOrderItem, serviceOrder);
94 } else if (macroService) {
95 LOGGER.info("Mode type macro");
96 // call SO macro flow.(EXTAPI-368)
97 ResponseEntity<CreateMacroServiceInstanceResponse> response = postSoProcessor
98 .postMacroServiceOrderItem(serviceOrderInfo, serviceOrderItem);
99 updateMacroServiceOrderItem(response, serviceOrderItem, serviceOrder);
102 ResponseEntity<CreateServiceInstanceResponse> response =
103 postSoProcessor.postServiceOrderItem(serviceOrderInfo, serviceOrderItem);
104 updateServiceOrderItem(response, serviceOrderItem, serviceOrder);
108 boolean shouldStopPolling = shouldStopPolling(executionTask);
109 if (!shouldStopPolling && StateType.FAILED != serviceOrderItem.getState()) {
110 // TODO lancer en asynchrone
111 sOGetStatusManager.pollRequestStatus(serviceOrder, serviceOrderItem, e2eService);
113 if (serviceOrderItem.getState().equals(StateType.COMPLETED)) {
114 updateSuccessTask(executionTask);
116 } else if (shouldStopPolling && StateType.FAILED != serviceOrderItem.getState()) {
117 serviceOrderService.addOrderItemMessage(serviceOrder, serviceOrderItem, "504");
118 updateFailedTask(executionTask, serviceOrder);
120 updateFailedTask(executionTask, serviceOrder);
123 updateServiceOrder(serviceOrder);
126 private boolean shouldPostSo(ServiceOrderItem serviceOrderItem) {
127 return StateType.ACKNOWLEDGED == serviceOrderItem.getState()
128 || StateType.INPROGRESS_MODIFY_ITEM_TO_CREATE == serviceOrderItem.getState();
131 private ServiceOrderItem getServiceOrderItem(ExecutionTask executionTask, ServiceOrder serviceOrder) {
132 for (ServiceOrderItem item : serviceOrder.getOrderItem()) {
133 if (item.getId().equals(executionTask.getOrderItemId())) {
137 throw new TechnicalException(
138 "Unable to retrieve serviceOrderItem for executionTaskId " + executionTask.getInternalId());
141 private ServiceOrderInfo getServiceOrderInfo(ExecutionTask executionTask) {
142 String serviceOrderInfoJson = executionTask.getServiceOrderInfoJson();
143 ServiceOrderInfo serviceOrderInfo = null;
145 serviceOrderInfo = JsonEntityConverter.convertJsonToServiceOrderInfo(serviceOrderInfoJson);
146 } catch (IOException e) {
147 LOGGER.error("Unable to read ServiceOrderInfo Json for executionTaskId " + executionTask.getInternalId(),
149 throw new TechnicalException(
150 "Unable to read ServiceOrderInfo Json for executionTaskId " + executionTask.getInternalId());
152 return serviceOrderInfo;
155 private void updateServiceOrder(ServiceOrder serviceOrder) {
156 boolean atLeastOneCompleted = false;
157 boolean atLeastOneNotFinished = false;
158 boolean atLeastOneFailed = false;
160 for (ServiceOrderItem serviceOrderItem : serviceOrder.getOrderItem()) {
161 switch (serviceOrderItem.getState()) {
163 atLeastOneCompleted = true;
167 atLeastOneNotFinished = true;
170 atLeastOneFailed = true;
177 if (atLeastOneNotFinished) {
178 serviceOrderService.updateOrderState(serviceOrder, StateType.INPROGRESS);
180 StateType finalState;
181 if (atLeastOneFailed) {
182 if (!atLeastOneCompleted) {
183 finalState = StateType.FAILED;
185 finalState = StateType.PARTIAL;
188 finalState = StateType.COMPLETED;
190 serviceOrderService.updateOrderState(serviceOrder, finalState);
195 * Update ServiceOrderItem with SO response by using serviceOrderRepository with the serviceOrderId
197 private void updateServiceOrderItem(ResponseEntity<CreateServiceInstanceResponse> response,
198 ServiceOrderItem orderItem, ServiceOrder serviceOrder) {
200 if (response == null || !response.getStatusCode().is2xxSuccessful()) {
201 LOGGER.warn("response ko for serviceOrderItem.id=" + orderItem.getId());
202 serviceOrderService.updateOrderItemState(serviceOrder, orderItem, StateType.FAILED);
203 buildOrderMessageIfNeeded(orderItem, serviceOrder, response);
205 CreateServiceInstanceResponse createServiceInstanceResponse = response.getBody();
206 if (createServiceInstanceResponse != null && !orderItem.getState().equals(StateType.FAILED)) {
207 orderItem.getService().setId(createServiceInstanceResponse.getRequestReferences().getInstanceId());
208 orderItem.setRequestId(createServiceInstanceResponse.getRequestReferences().getRequestId());
211 if (!response.getStatusCode().is2xxSuccessful() || response.getBody() == null
212 || response.getBody().getRequestReferences() == null) {
213 serviceOrderService.updateOrderItemState(serviceOrder, orderItem, StateType.FAILED);
214 LOGGER.warn("order item {} failed , status {} , response {}", orderItem.getId(),
215 response.getStatusCode(), response.getBody());
217 updateOrderItemToInProgress(serviceOrder, orderItem);
223 * Update ServiceOrderItem with SO response by using serviceOrderRepository with the serviceOrderId
225 private void updateMacroServiceOrderItem(ResponseEntity<CreateMacroServiceInstanceResponse> response,
226 ServiceOrderItem orderItem, ServiceOrder serviceOrder) {
228 if (response == null || !response.getStatusCode().is2xxSuccessful()) {
229 LOGGER.warn("response ko for serviceOrderItem.id=" + orderItem.getId());
230 serviceOrderService.updateOrderItemState(serviceOrder, orderItem, StateType.FAILED);
231 buildOrderMessageIfNeeded(orderItem, serviceOrder, response);
233 CreateMacroServiceInstanceResponse createMacroServiceInstanceResponse = response.getBody();
234 if (createMacroServiceInstanceResponse != null && !orderItem.getState().equals(StateType.FAILED)) {
235 orderItem.getService().setId(createMacroServiceInstanceResponse.getRequestReferences().getInstanceId());
236 orderItem.setRequestId(createMacroServiceInstanceResponse.getRequestReferences().getRequestId());
239 if (!response.getStatusCode().is2xxSuccessful() || response.getBody() == null
240 || response.getBody().getRequestReferences() == null) {
241 serviceOrderService.updateOrderItemState(serviceOrder, orderItem, StateType.FAILED);
243 .warn("order item {} failed , status {} , response {}", orderItem.getId(), response.getStatusCode(),
246 serviceOrderService.updateOrderItemState(serviceOrder, orderItem, StateType.INPROGRESS);
251 private void updateOrderItemToInProgress(ServiceOrder serviceOrder, ServiceOrderItem serviceOrderItem) {
252 if (serviceOrderItem.getAction() != ActionType.MODIFY) {
253 serviceOrderService.updateOrderItemState(serviceOrder, serviceOrderItem, StateType.INPROGRESS);
255 if (StateType.ACKNOWLEDGED == serviceOrderItem.getState()) {
256 serviceOrderService.updateOrderItemState(serviceOrder, serviceOrderItem,
257 StateType.INPROGRESS_MODIFY_REQUEST_DELETE_SEND);
259 serviceOrderService.updateOrderItemState(serviceOrder, serviceOrderItem,
260 StateType.INPROGRESS_MODIFY_REQUEST_CREATE_SEND);
265 private void buildOrderMessageIfNeeded(ServiceOrderItem serviceOrderItem, ServiceOrder serviceOrder,
266 ResponseEntity<?> response) {
267 if (response != null) {
268 if (response.getStatusCode() == HttpStatus.INTERNAL_SERVER_ERROR) {
269 serviceOrderService.addOrderMessage(serviceOrder, "502");
270 } else if (response.getStatusCode() == HttpStatus.BAD_REQUEST) {
271 ResponseEntity<?> messageError = response;
272 if (messageError.getBody().toString().toLowerCase().contains("serviceinstance already exists")) {
273 serviceOrderService.addOrderItemMessage(serviceOrder, serviceOrderItem, "105");
275 serviceOrderService.addOrderItemMessageRequestSo(serviceOrder, serviceOrderItem,
276 messageError.getBody().toString());
283 * Update E2EServiceOrderItem with SO response by using serviceOrderRepository with the serviceOrderId
285 private void updateE2EServiceOrderItem(ResponseEntity<CreateE2EServiceInstanceResponse> response,
286 ServiceOrderItem orderItem, ServiceOrder serviceOrder) {
288 if (response == null || !response.getStatusCode().is2xxSuccessful()) {
289 LOGGER.warn("response ko for serviceOrderItem.id=" + orderItem.getId());
290 serviceOrderService.updateOrderItemState(serviceOrder, orderItem, StateType.FAILED);
292 CreateE2EServiceInstanceResponse createE2EServiceInstanceResponse = response.getBody();
293 if (createE2EServiceInstanceResponse != null && !orderItem.getState().equals(StateType.FAILED)) {
294 orderItem.getService().setId(createE2EServiceInstanceResponse.getService().getServiceId());
295 orderItem.setRequestId(createE2EServiceInstanceResponse.getService().getOperationId());
298 if (!response.getStatusCode().is2xxSuccessful() || response.getBody() == null
299 || response.getBody().getService().getOperationId() == null
300 || response.getBody().getService().getServiceId() == null) {
301 serviceOrderService.updateOrderItemState(serviceOrder, orderItem, StateType.FAILED);
302 LOGGER.warn("order item {} failed , status {} , response {}", orderItem.getId(),
303 response.getStatusCode(), response.getBody());
305 serviceOrderService.updateOrderItemState(serviceOrder, orderItem, StateType.INPROGRESS);
311 * Update an executionTask in database when it's process with a success
313 private void updateSuccessTask(ExecutionTask executionTask) {
314 executionTaskRepository.deleteById(executionTask.getInternalId());
315 executionTaskRepository.updateReliedTaskAfterDelete(executionTask.getInternalId());
320 * @param executionTask
321 * @param serviceOrder
323 private void updateFailedTask(ExecutionTask executionTask, ServiceOrder serviceOrder) {
324 List<ExecutionTask> executionTasksToDelete = findExecutionTasksRecursively(executionTask);
325 for (ExecutionTask taskId : executionTasksToDelete) {
326 executionTaskRepository.delete(taskId);
327 LOGGER.warn("task {} with orderitem id {} deleted cause orderitem id {} failed ", taskId.getInternalId(),
328 taskId.getOrderItemId(), executionTask.getOrderItemId());
330 for (ServiceOrderItem item : serviceOrder.getOrderItem()) {
331 for (ExecutionTask taskToDelete : executionTasksToDelete) {
332 if (taskToDelete.getOrderItemId().equals(item.getId())) {
333 serviceOrderService.updateOrderItemState(serviceOrder, item, StateType.FAILED);
334 LOGGER.warn("task {} with orderitem id {} failed cause orderitem id {} failed ",
335 taskToDelete.getInternalId(), taskToDelete.getOrderItemId(),
336 executionTask.getOrderItemId());
344 * @param executionTask
347 private List<ExecutionTask> findExecutionTasksRecursively(ExecutionTask executionTask) {
349 List<ExecutionTask> executionTasks = new ArrayList<>();
351 List<ExecutionTask> tasksReliedToAnOrderItemId =
352 executionTaskRepository.findTasksReliedToAnOrderItemId(executionTask.getInternalId());
354 if (CollectionUtils.isEmpty(tasksReliedToAnOrderItemId)) {
355 return Arrays.asList(executionTask);
357 for (ExecutionTask task : tasksReliedToAnOrderItemId) {
358 executionTasks.addAll(findExecutionTasksRecursively(task));
361 executionTasks.add(executionTask);
362 return executionTasks;
365 private boolean shouldStopPolling(ExecutionTask executionTask) {
366 long createTimeinMillis = executionTask.getCreateDate().getTime();
367 long lastAttemptTimeInMillis = executionTask.getLastAttemptDate().getTime();
368 long differenceInMillis = lastAttemptTimeInMillis - createTimeinMillis;
369 float pollingDurationInMillis = pollingDurationInMins * 60000;
370 LOGGER.debug("Task {} with orderitem id {}: Task create date: {} Task last attempt date: {}",
371 executionTask.getInternalId(), executionTask.getOrderItemId(), createTimeinMillis,
372 lastAttemptTimeInMillis);
373 LOGGER.debug("Difference {} and Polling Duration {}", differenceInMillis, pollingDurationInMins);
374 return (differenceInMillis > pollingDurationInMillis);