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.
13 package org.onap.nbi.apis.serviceorder.workflow;
15 import java.io.IOException;
16 import java.util.ArrayList;
17 import java.util.Arrays;
18 import java.util.Date;
19 import java.util.List;
20 import java.util.Optional;
21 import org.onap.nbi.apis.serviceorder.model.ActionType;
22 import org.onap.nbi.apis.serviceorder.model.ServiceOrder;
23 import org.onap.nbi.apis.serviceorder.model.ServiceOrderItem;
24 import org.onap.nbi.apis.serviceorder.model.StateType;
25 import org.onap.nbi.apis.serviceorder.model.consumer.CreateE2EServiceInstanceResponse;
26 import org.onap.nbi.apis.serviceorder.model.consumer.CreateServiceInstanceResponse;
27 import org.onap.nbi.apis.serviceorder.model.orchestrator.ExecutionTask;
28 import org.onap.nbi.apis.serviceorder.model.orchestrator.ServiceOrderInfo;
29 import org.onap.nbi.apis.serviceorder.repositories.ExecutionTaskRepository;
30 import org.onap.nbi.apis.serviceorder.service.ServiceOrderService;
31 import org.onap.nbi.apis.serviceorder.utils.E2EServiceUtils;
32 import org.onap.nbi.apis.serviceorder.utils.JsonEntityConverter;
33 import org.onap.nbi.exceptions.TechnicalException;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
36 import org.springframework.beans.factory.annotation.Autowired;
37 import org.springframework.beans.factory.annotation.Value;
38 import org.springframework.http.HttpStatus;
39 import org.springframework.http.ResponseEntity;
40 import org.springframework.stereotype.Service;
41 import org.springframework.util.CollectionUtils;
44 public class SOTaskProcessor {
48 private ServiceOrderService serviceOrderService;
51 private ExecutionTaskRepository executionTaskRepository;
54 private PostSoProcessor postSoProcessor;
57 private SOGetStatusManager sOGetStatusManager;
59 @Value("${scheduler.pollingDurationInMins}")
60 private float pollingDurationInMins;
62 private static final Logger LOGGER = LoggerFactory.getLogger(SOTaskProcessor.class);
65 * Run the ServiceOrchestrator processing for a serviceOrderItem which with any sub relations
67 public void processOrderItem(ExecutionTask executionTask) {
69 executionTask.setLastAttemptDate(new Date());
70 executionTaskRepository.save(executionTask);
72 ServiceOrderInfo serviceOrderInfo = getServiceOrderInfo(executionTask);
74 Optional<ServiceOrder> optionalServiceOrder = serviceOrderService
75 .findServiceOrderById(serviceOrderInfo.getServiceOrderId());
76 if (!optionalServiceOrder.isPresent()) {
77 throw new TechnicalException(
78 "Unable to retrieve service order for id " + serviceOrderInfo.getServiceOrderId());
80 ServiceOrder serviceOrder = optionalServiceOrder.get();
81 ServiceOrderItem serviceOrderItem = getServiceOrderItem(executionTask, serviceOrder);
82 boolean e2eService = E2EServiceUtils
83 .isE2EService(serviceOrderInfo.getServiceOrderItemInfos().get(serviceOrderItem.getId()));
85 if (shouldPostSo(serviceOrderItem)) {
87 ResponseEntity<CreateE2EServiceInstanceResponse> response = postSoProcessor
88 .postE2EServiceOrderItem(serviceOrderInfo,
89 serviceOrderItem, serviceOrder);
90 updateE2EServiceOrderItem(response, serviceOrderItem, serviceOrder);
93 ResponseEntity<CreateServiceInstanceResponse> response = postSoProcessor
94 .postServiceOrderItem(serviceOrderInfo, serviceOrderItem);
95 updateServiceOrderItem(response, serviceOrderItem, serviceOrder);
99 boolean shouldStopPolling = shouldStopPolling(executionTask);
100 if (!shouldStopPolling && StateType.FAILED != serviceOrderItem.getState()
102 // TODO lancer en asynchrone
103 sOGetStatusManager.pollRequestStatus(serviceOrder, serviceOrderItem, e2eService);
105 if (serviceOrderItem.getState().equals(StateType.COMPLETED)) {
106 updateSuccessTask(executionTask);
108 } else if (shouldStopPolling && StateType.FAILED != serviceOrderItem.getState()) {
109 serviceOrderService.addOrderItemMessage(serviceOrder, serviceOrderItem, "504");
110 updateFailedTask(executionTask, serviceOrder);
112 updateFailedTask(executionTask, serviceOrder);
115 updateServiceOrder(serviceOrder);
118 private boolean shouldPostSo(ServiceOrderItem serviceOrderItem) {
119 return StateType.ACKNOWLEDGED == serviceOrderItem.getState()
120 || StateType.INPROGRESS_MODIFY_ITEM_TO_CREATE == serviceOrderItem.getState();
123 private ServiceOrderItem getServiceOrderItem(ExecutionTask executionTask, ServiceOrder serviceOrder) {
124 for (ServiceOrderItem item : serviceOrder.getOrderItem()) {
125 if (item.getId().equals(executionTask.getOrderItemId())) {
129 throw new TechnicalException(
130 "Unable to retrieve serviceOrderItem for executionTaskId " + executionTask.getInternalId());
133 private ServiceOrderInfo getServiceOrderInfo(ExecutionTask executionTask) {
134 String serviceOrderInfoJson = executionTask.getServiceOrderInfoJson();
135 ServiceOrderInfo serviceOrderInfo = null;
138 JsonEntityConverter.convertJsonToServiceOrderInfo(serviceOrderInfoJson);
139 } catch (IOException e) {
141 .error("Unable to read ServiceOrderInfo Json for executionTaskId " + executionTask.getInternalId(), e);
142 throw new TechnicalException(
143 "Unable to read ServiceOrderInfo Json for executionTaskId " + executionTask.getInternalId());
145 return serviceOrderInfo;
149 private void updateServiceOrder(ServiceOrder serviceOrder) {
150 boolean atLeastOneCompleted = false;
151 boolean atLeastOneNotFinished = false;
152 boolean atLeastOneFailed = false;
154 for (ServiceOrderItem serviceOrderItem : serviceOrder.getOrderItem()) {
155 switch (serviceOrderItem.getState()) {
157 atLeastOneCompleted = true;
161 atLeastOneNotFinished = true;
164 atLeastOneFailed = true;
171 if (atLeastOneNotFinished) {
172 serviceOrderService.updateOrderState(serviceOrder, StateType.INPROGRESS);
174 StateType finalState;
175 if (atLeastOneFailed) {
176 if (!atLeastOneCompleted) {
177 finalState = StateType.FAILED;
179 finalState = StateType.PARTIAL;
182 finalState = StateType.COMPLETED;
184 serviceOrderService.updateOrderState(serviceOrder, finalState);
190 * Update ServiceOrderItem with SO response by using serviceOrderRepository with the serviceOrderId
192 private void updateServiceOrderItem(ResponseEntity<CreateServiceInstanceResponse> response,
193 ServiceOrderItem orderItem, ServiceOrder serviceOrder) {
195 if (response == null || !response.getStatusCode().is2xxSuccessful()) {
196 LOGGER.warn("response ko for serviceOrderItem.id=" + orderItem.getId());
197 serviceOrderService.updateOrderItemState(serviceOrder, orderItem, StateType.FAILED);
198 buildOrderMessageIfNeeded(orderItem, serviceOrder, response);
200 CreateServiceInstanceResponse createServiceInstanceResponse = response.getBody();
201 if (createServiceInstanceResponse != null && !orderItem.getState().equals(StateType.FAILED)) {
202 orderItem.getService().setId(createServiceInstanceResponse.getRequestReferences().getInstanceId());
203 orderItem.setRequestId(createServiceInstanceResponse.getRequestReferences().getRequestId());
206 if (!response.getStatusCode().is2xxSuccessful() || response.getBody() == null
207 || response.getBody().getRequestReferences() == null) {
208 serviceOrderService.updateOrderItemState(serviceOrder, orderItem, StateType.FAILED);
210 .warn("order item {} failed , status {} , response {}", orderItem.getId(), response.getStatusCode(),
213 updateOrderItemToInProgress(serviceOrder, orderItem);
219 private void updateOrderItemToInProgress(ServiceOrder serviceOrder, ServiceOrderItem serviceOrderItem) {
220 if (serviceOrderItem.getAction() != ActionType.MODIFY) {
221 serviceOrderService.updateOrderItemState(serviceOrder, serviceOrderItem, StateType.INPROGRESS);
223 if (StateType.ACKNOWLEDGED == serviceOrderItem.getState()) {
224 serviceOrderService.updateOrderItemState(serviceOrder, serviceOrderItem,
225 StateType.INPROGRESS_MODIFY_REQUEST_DELETE_SEND);
227 serviceOrderService.updateOrderItemState(serviceOrder, serviceOrderItem,
228 StateType.INPROGRESS_MODIFY_REQUEST_CREATE_SEND);
234 private void buildOrderMessageIfNeeded(ServiceOrderItem serviceOrderItem, ServiceOrder serviceOrder,
235 ResponseEntity<?> response) {
236 if (response != null) {
237 if (response.getStatusCode() == HttpStatus.INTERNAL_SERVER_ERROR) {
238 serviceOrderService.addOrderMessage(serviceOrder, "502");
239 } else if (response.getStatusCode() == HttpStatus.BAD_REQUEST) {
240 ResponseEntity<?> messageError = response;
241 if (messageError.getBody().toString().toLowerCase().contains("serviceinstance already exists")) {
242 serviceOrderService.addOrderItemMessage(serviceOrder, serviceOrderItem, "105");
244 serviceOrderService.addOrderItemMessageRequestSo(serviceOrder, serviceOrderItem,
245 messageError.getBody().toString());
252 * Update E2EServiceOrderItem with SO response by using serviceOrderRepository with the serviceOrderId
254 private void updateE2EServiceOrderItem(ResponseEntity<CreateE2EServiceInstanceResponse> response,
255 ServiceOrderItem orderItem, ServiceOrder serviceOrder) {
257 if (response == null || !response.getStatusCode().is2xxSuccessful()) {
258 LOGGER.warn("response ko for serviceOrderItem.id=" + orderItem.getId());
259 serviceOrderService.updateOrderItemState(serviceOrder, orderItem, StateType.FAILED);
261 CreateE2EServiceInstanceResponse createE2EServiceInstanceResponse = response.getBody();
262 if (createE2EServiceInstanceResponse != null && !orderItem.getState().equals(StateType.FAILED)) {
263 orderItem.getService().setId(createE2EServiceInstanceResponse.getService().getServiceId());
264 orderItem.setRequestId(createE2EServiceInstanceResponse.getService().getOperationId());
267 if (!response.getStatusCode().is2xxSuccessful() || response.getBody() == null
268 || response.getBody().getService().getOperationId() == null
269 || response.getBody().getService().getServiceId() == null) {
270 serviceOrderService.updateOrderItemState(serviceOrder, orderItem, StateType.FAILED);
272 .warn("order item {} failed , status {} , response {}", orderItem.getId(), response.getStatusCode(),
275 serviceOrderService.updateOrderItemState(serviceOrder, orderItem, StateType.INPROGRESS);
281 * Update an executionTask in database when it's process with a success
283 private void updateSuccessTask(ExecutionTask executionTask) {
284 executionTaskRepository.deleteById(executionTask.getInternalId());
285 executionTaskRepository.updateReliedTaskAfterDelete(executionTask.getInternalId());
290 * @param executionTask
291 * @param serviceOrder
293 private void updateFailedTask(ExecutionTask executionTask, ServiceOrder serviceOrder) {
294 List<ExecutionTask> executionTasksToDelete = findExecutionTasksRecursively(executionTask);
295 for (ExecutionTask taskId : executionTasksToDelete) {
296 executionTaskRepository.delete(taskId);
297 LOGGER.warn("task {} with orderitem id {} deleted cause orderitem id {} failed ", taskId.getInternalId(),
298 taskId.getOrderItemId(), executionTask.getOrderItemId());
300 for (ServiceOrderItem item : serviceOrder.getOrderItem()) {
301 for (ExecutionTask taskToDelete : executionTasksToDelete) {
302 if (taskToDelete.getOrderItemId().equals(item.getId())) {
303 serviceOrderService.updateOrderItemState(serviceOrder, item, StateType.FAILED);
304 LOGGER.warn("task {} with orderitem id {} failed cause orderitem id {} failed ",
305 taskToDelete.getInternalId(), taskToDelete.getOrderItemId(), executionTask.getOrderItemId());
313 * @param executionTask
316 private List<ExecutionTask> findExecutionTasksRecursively(ExecutionTask executionTask) {
318 List<ExecutionTask> executionTasks = new ArrayList<>();
320 List<ExecutionTask> tasksReliedToAnOrderItemId =
321 executionTaskRepository.findTasksReliedToAnOrderItemId(executionTask.getInternalId());
323 if (CollectionUtils.isEmpty(tasksReliedToAnOrderItemId)) {
324 return Arrays.asList(executionTask);
326 for (ExecutionTask task : tasksReliedToAnOrderItemId) {
327 executionTasks.addAll(findExecutionTasksRecursively(task));
330 executionTasks.add(executionTask);
331 return executionTasks;
334 private boolean shouldStopPolling(ExecutionTask executionTask) {
335 long createTimeinMillis = executionTask.getCreateDate().getTime();
336 long lastAttemptTimeInMillis = executionTask.getLastAttemptDate().getTime();
337 long differenceInMillis = lastAttemptTimeInMillis - createTimeinMillis;
338 float pollingDurationInMillis = pollingDurationInMins * 60000;
339 LOGGER.debug("Task {} with orderitem id {}: Task create date: {} Task last attempt date: {}",
340 executionTask.getInternalId(), executionTask.getOrderItemId(), createTimeinMillis,
341 lastAttemptTimeInMillis);
342 LOGGER.debug("Difference {} and Polling Duration {}",
343 differenceInMillis, pollingDurationInMins);
344 return (differenceInMillis > pollingDurationInMillis);