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.CreateServiceInstanceResponse;
28 import org.onap.nbi.apis.serviceorder.model.orchestrator.ExecutionTask;
29 import org.onap.nbi.apis.serviceorder.model.orchestrator.ServiceOrderInfo;
30 import org.onap.nbi.apis.serviceorder.repositories.ExecutionTaskRepository;
31 import org.onap.nbi.apis.serviceorder.service.ServiceOrderService;
32 import org.onap.nbi.apis.serviceorder.utils.E2EServiceUtils;
33 import org.onap.nbi.apis.serviceorder.utils.JsonEntityConverter;
34 import org.onap.nbi.exceptions.TechnicalException;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
37 import org.springframework.beans.factory.annotation.Autowired;
38 import org.springframework.beans.factory.annotation.Value;
39 import org.springframework.http.HttpStatus;
40 import org.springframework.http.ResponseEntity;
41 import org.springframework.stereotype.Service;
42 import org.springframework.util.CollectionUtils;
45 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 =
75 serviceOrderService.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);
83 E2EServiceUtils.isE2EService(serviceOrderInfo.getServiceOrderItemInfos().get(serviceOrderItem.getId()));
85 if (shouldPostSo(serviceOrderItem)) {
87 ResponseEntity<CreateE2EServiceInstanceResponse> response =
88 postSoProcessor.postE2EServiceOrderItem(serviceOrderInfo, serviceOrderItem, serviceOrder);
89 updateE2EServiceOrderItem(response, serviceOrderItem, serviceOrder);
92 ResponseEntity<CreateServiceInstanceResponse> response =
93 postSoProcessor.postServiceOrderItem(serviceOrderInfo, serviceOrderItem);
94 updateServiceOrderItem(response, serviceOrderItem, serviceOrder);
98 boolean shouldStopPolling = shouldStopPolling(executionTask);
99 if (!shouldStopPolling && StateType.FAILED != serviceOrderItem.getState()) {
100 // TODO lancer en asynchrone
101 sOGetStatusManager.pollRequestStatus(serviceOrder, serviceOrderItem, e2eService);
103 if (serviceOrderItem.getState().equals(StateType.COMPLETED)) {
104 updateSuccessTask(executionTask);
106 } else if (shouldStopPolling && StateType.FAILED != serviceOrderItem.getState()) {
107 serviceOrderService.addOrderItemMessage(serviceOrder, serviceOrderItem, "504");
108 updateFailedTask(executionTask, serviceOrder);
110 updateFailedTask(executionTask, serviceOrder);
113 updateServiceOrder(serviceOrder);
116 private boolean shouldPostSo(ServiceOrderItem serviceOrderItem) {
117 return StateType.ACKNOWLEDGED == serviceOrderItem.getState()
118 || StateType.INPROGRESS_MODIFY_ITEM_TO_CREATE == serviceOrderItem.getState();
121 private ServiceOrderItem getServiceOrderItem(ExecutionTask executionTask, ServiceOrder serviceOrder) {
122 for (ServiceOrderItem item : serviceOrder.getOrderItem()) {
123 if (item.getId().equals(executionTask.getOrderItemId())) {
127 throw new TechnicalException(
128 "Unable to retrieve serviceOrderItem for executionTaskId " + executionTask.getInternalId());
131 private ServiceOrderInfo getServiceOrderInfo(ExecutionTask executionTask) {
132 String serviceOrderInfoJson = executionTask.getServiceOrderInfoJson();
133 ServiceOrderInfo serviceOrderInfo = null;
135 serviceOrderInfo = JsonEntityConverter.convertJsonToServiceOrderInfo(serviceOrderInfoJson);
136 } catch (IOException e) {
137 LOGGER.error("Unable to read ServiceOrderInfo Json for executionTaskId " + executionTask.getInternalId(),
139 throw new TechnicalException(
140 "Unable to read ServiceOrderInfo Json for executionTaskId " + executionTask.getInternalId());
142 return serviceOrderInfo;
145 private void updateServiceOrder(ServiceOrder serviceOrder) {
146 boolean atLeastOneCompleted = false;
147 boolean atLeastOneNotFinished = false;
148 boolean atLeastOneFailed = false;
150 for (ServiceOrderItem serviceOrderItem : serviceOrder.getOrderItem()) {
151 switch (serviceOrderItem.getState()) {
153 atLeastOneCompleted = true;
157 atLeastOneNotFinished = true;
160 atLeastOneFailed = true;
167 if (atLeastOneNotFinished) {
168 serviceOrderService.updateOrderState(serviceOrder, StateType.INPROGRESS);
170 StateType finalState;
171 if (atLeastOneFailed) {
172 if (!atLeastOneCompleted) {
173 finalState = StateType.FAILED;
175 finalState = StateType.PARTIAL;
178 finalState = StateType.COMPLETED;
180 serviceOrderService.updateOrderState(serviceOrder, finalState);
185 * Update ServiceOrderItem with SO response by using serviceOrderRepository with the serviceOrderId
187 private void updateServiceOrderItem(ResponseEntity<CreateServiceInstanceResponse> response,
188 ServiceOrderItem orderItem, ServiceOrder serviceOrder) {
190 if (response == null || !response.getStatusCode().is2xxSuccessful()) {
191 LOGGER.warn("response ko for serviceOrderItem.id=" + orderItem.getId());
192 serviceOrderService.updateOrderItemState(serviceOrder, orderItem, StateType.FAILED);
193 buildOrderMessageIfNeeded(orderItem, serviceOrder, response);
195 CreateServiceInstanceResponse createServiceInstanceResponse = response.getBody();
196 if (createServiceInstanceResponse != null && !orderItem.getState().equals(StateType.FAILED)) {
197 orderItem.getService().setId(createServiceInstanceResponse.getRequestReferences().getInstanceId());
198 orderItem.setRequestId(createServiceInstanceResponse.getRequestReferences().getRequestId());
201 if (!response.getStatusCode().is2xxSuccessful() || response.getBody() == null
202 || response.getBody().getRequestReferences() == null) {
203 serviceOrderService.updateOrderItemState(serviceOrder, orderItem, StateType.FAILED);
204 LOGGER.warn("order item {} failed , status {} , response {}", orderItem.getId(),
205 response.getStatusCode(), response.getBody());
207 updateOrderItemToInProgress(serviceOrder, orderItem);
212 private void updateOrderItemToInProgress(ServiceOrder serviceOrder, ServiceOrderItem serviceOrderItem) {
213 if (serviceOrderItem.getAction() != ActionType.MODIFY) {
214 serviceOrderService.updateOrderItemState(serviceOrder, serviceOrderItem, StateType.INPROGRESS);
216 if (StateType.ACKNOWLEDGED == serviceOrderItem.getState()) {
217 serviceOrderService.updateOrderItemState(serviceOrder, serviceOrderItem,
218 StateType.INPROGRESS_MODIFY_REQUEST_DELETE_SEND);
220 serviceOrderService.updateOrderItemState(serviceOrder, serviceOrderItem,
221 StateType.INPROGRESS_MODIFY_REQUEST_CREATE_SEND);
226 private void buildOrderMessageIfNeeded(ServiceOrderItem serviceOrderItem, ServiceOrder serviceOrder,
227 ResponseEntity<?> response) {
228 if (response != null) {
229 if (response.getStatusCode() == HttpStatus.INTERNAL_SERVER_ERROR) {
230 serviceOrderService.addOrderMessage(serviceOrder, "502");
231 } else if (response.getStatusCode() == HttpStatus.BAD_REQUEST) {
232 ResponseEntity<?> messageError = response;
233 if (messageError.getBody().toString().toLowerCase().contains("serviceinstance already exists")) {
234 serviceOrderService.addOrderItemMessage(serviceOrder, serviceOrderItem, "105");
236 serviceOrderService.addOrderItemMessageRequestSo(serviceOrder, serviceOrderItem,
237 messageError.getBody().toString());
244 * Update E2EServiceOrderItem with SO response by using serviceOrderRepository with the serviceOrderId
246 private void updateE2EServiceOrderItem(ResponseEntity<CreateE2EServiceInstanceResponse> response,
247 ServiceOrderItem orderItem, ServiceOrder serviceOrder) {
249 if (response == null || !response.getStatusCode().is2xxSuccessful()) {
250 LOGGER.warn("response ko for serviceOrderItem.id=" + orderItem.getId());
251 serviceOrderService.updateOrderItemState(serviceOrder, orderItem, StateType.FAILED);
253 CreateE2EServiceInstanceResponse createE2EServiceInstanceResponse = response.getBody();
254 if (createE2EServiceInstanceResponse != null && !orderItem.getState().equals(StateType.FAILED)) {
255 orderItem.getService().setId(createE2EServiceInstanceResponse.getService().getServiceId());
256 orderItem.setRequestId(createE2EServiceInstanceResponse.getService().getOperationId());
259 if (!response.getStatusCode().is2xxSuccessful() || response.getBody() == null
260 || response.getBody().getService().getOperationId() == null
261 || response.getBody().getService().getServiceId() == null) {
262 serviceOrderService.updateOrderItemState(serviceOrder, orderItem, StateType.FAILED);
263 LOGGER.warn("order item {} failed , status {} , response {}", orderItem.getId(),
264 response.getStatusCode(), response.getBody());
266 serviceOrderService.updateOrderItemState(serviceOrder, orderItem, StateType.INPROGRESS);
272 * Update an executionTask in database when it's process with a success
274 private void updateSuccessTask(ExecutionTask executionTask) {
275 executionTaskRepository.deleteById(executionTask.getInternalId());
276 executionTaskRepository.updateReliedTaskAfterDelete(executionTask.getInternalId());
281 * @param executionTask
282 * @param serviceOrder
284 private void updateFailedTask(ExecutionTask executionTask, ServiceOrder serviceOrder) {
285 List<ExecutionTask> executionTasksToDelete = findExecutionTasksRecursively(executionTask);
286 for (ExecutionTask taskId : executionTasksToDelete) {
287 executionTaskRepository.delete(taskId);
288 LOGGER.warn("task {} with orderitem id {} deleted cause orderitem id {} failed ", taskId.getInternalId(),
289 taskId.getOrderItemId(), executionTask.getOrderItemId());
291 for (ServiceOrderItem item : serviceOrder.getOrderItem()) {
292 for (ExecutionTask taskToDelete : executionTasksToDelete) {
293 if (taskToDelete.getOrderItemId().equals(item.getId())) {
294 serviceOrderService.updateOrderItemState(serviceOrder, item, StateType.FAILED);
295 LOGGER.warn("task {} with orderitem id {} failed cause orderitem id {} failed ",
296 taskToDelete.getInternalId(), taskToDelete.getOrderItemId(),
297 executionTask.getOrderItemId());
305 * @param executionTask
308 private List<ExecutionTask> findExecutionTasksRecursively(ExecutionTask executionTask) {
310 List<ExecutionTask> executionTasks = new ArrayList<>();
312 List<ExecutionTask> tasksReliedToAnOrderItemId =
313 executionTaskRepository.findTasksReliedToAnOrderItemId(executionTask.getInternalId());
315 if (CollectionUtils.isEmpty(tasksReliedToAnOrderItemId)) {
316 return Arrays.asList(executionTask);
318 for (ExecutionTask task : tasksReliedToAnOrderItemId) {
319 executionTasks.addAll(findExecutionTasksRecursively(task));
322 executionTasks.add(executionTask);
323 return executionTasks;
326 private boolean shouldStopPolling(ExecutionTask executionTask) {
327 long createTimeinMillis = executionTask.getCreateDate().getTime();
328 long lastAttemptTimeInMillis = executionTask.getLastAttemptDate().getTime();
329 long differenceInMillis = lastAttemptTimeInMillis - createTimeinMillis;
330 float pollingDurationInMillis = pollingDurationInMins * 60000;
331 LOGGER.debug("Task {} with orderitem id {}: Task create date: {} Task last attempt date: {}",
332 executionTask.getInternalId(), executionTask.getOrderItemId(), createTimeinMillis,
333 lastAttemptTimeInMillis);
334 LOGGER.debug("Difference {} and Polling Duration {}", differenceInMillis, pollingDurationInMins);
335 return (differenceInMillis > pollingDurationInMillis);