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 org.onap.nbi.apis.serviceorder.model.ActionType;
21 import org.onap.nbi.apis.serviceorder.model.ServiceOrder;
22 import org.onap.nbi.apis.serviceorder.model.ServiceOrderItem;
23 import org.onap.nbi.apis.serviceorder.model.StateType;
24 import org.onap.nbi.apis.serviceorder.model.consumer.CreateE2EServiceInstanceResponse;
25 import org.onap.nbi.apis.serviceorder.model.consumer.CreateServiceInstanceResponse;
26 import org.onap.nbi.apis.serviceorder.model.orchestrator.ExecutionTask;
27 import org.onap.nbi.apis.serviceorder.model.orchestrator.ServiceOrderInfo;
28 import org.onap.nbi.apis.serviceorder.repositories.ExecutionTaskRepository;
29 import org.onap.nbi.apis.serviceorder.service.ServiceOrderService;
30 import org.onap.nbi.apis.serviceorder.utils.E2EServiceUtils;
31 import org.onap.nbi.apis.serviceorder.utils.JsonEntityConverter;
32 import org.onap.nbi.exceptions.TechnicalException;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
35 import org.springframework.beans.factory.annotation.Autowired;
36 import org.springframework.http.HttpStatus;
37 import org.springframework.http.ResponseEntity;
38 import org.springframework.stereotype.Service;
39 import org.springframework.util.CollectionUtils;
42 public class SOTaskProcessor {
46 private ServiceOrderService serviceOrderService;
49 private ExecutionTaskRepository executionTaskRepository;
52 private PostSoProcessor postSoProcessor;
55 private SOGetStatusManager sOGetStatusManager;
57 private static final Logger LOGGER = LoggerFactory.getLogger(SOTaskProcessor.class);
60 * Run the ServiceOrchestrator processing for a serviceOrderItem which with any sub relations
62 public void processOrderItem(ExecutionTask executionTask) throws InterruptedException {
64 ServiceOrderInfo serviceOrderInfo = getServiceOrderInfo(executionTask);
66 ServiceOrder serviceOrder = serviceOrderService.findServiceOrderById(serviceOrderInfo.getServiceOrderId());
67 ServiceOrderItem serviceOrderItem = getServiceOrderItem(executionTask, serviceOrder);
68 boolean e2eService = E2EServiceUtils
69 .isE2EService(serviceOrderInfo.getServiceOrderItemInfos().get(serviceOrderItem.getId()));
71 if (shouldPostSo(serviceOrderItem)) {
73 ResponseEntity<CreateE2EServiceInstanceResponse> response = postSoProcessor
74 .postE2EServiceOrderItem(serviceOrderInfo,
75 serviceOrderItem, serviceOrder);
76 updateE2EServiceOrderItem(response, serviceOrderItem, serviceOrder);
79 ResponseEntity<CreateServiceInstanceResponse> response = postSoProcessor
80 .postServiceOrderItem(serviceOrderInfo,serviceOrderItem);
81 updateServiceOrderItem(response, serviceOrderItem, serviceOrder);
85 if (executionTask.getNbRetries() > 0 && StateType.FAILED != serviceOrderItem.getState()
87 // TODO lancer en asynchrone
88 sOGetStatusManager.pollRequestStatus(serviceOrder, serviceOrderItem, e2eService);
90 if (serviceOrderItem.getState().equals(StateType.COMPLETED)) {
91 updateSuccessTask(executionTask);
92 } else if(shouldDecrementNbRetries(serviceOrderItem)){
93 int nbRetries = executionTask.getNbRetries();
94 executionTask.setNbRetries(--nbRetries);
95 executionTask.setLastAttemptDate(new Date());
96 executionTaskRepository.save(executionTask);
99 updateFailedTask(executionTask, serviceOrder);
102 updateServiceOrder(serviceOrder);
105 private boolean shouldDecrementNbRetries(ServiceOrderItem serviceOrderItem) {
106 return ActionType.MODIFY!=serviceOrderItem.getAction() || (StateType.INPROGRESS_MODIFY_REQUEST_CREATE_SEND ==serviceOrderItem.getState() || StateType.INPROGRESS_MODIFY_REQUEST_DELETE_SEND
107 ==serviceOrderItem.getState());
110 private boolean shouldPostSo(ServiceOrderItem serviceOrderItem) {
111 return StateType.ACKNOWLEDGED == serviceOrderItem.getState() || StateType.INPROGRESS_MODIFY_ITEM_TO_CREATE == serviceOrderItem.getState();
114 private ServiceOrderItem getServiceOrderItem(ExecutionTask executionTask, ServiceOrder serviceOrder) {
115 for (ServiceOrderItem item : serviceOrder.getOrderItem()) {
116 if (item.getId().equals(executionTask.getOrderItemId())) {
120 throw new TechnicalException(
121 "Unable to retrieve serviceOrderItem for executionTaskId " + executionTask.getInternalId());
124 private ServiceOrderInfo getServiceOrderInfo(ExecutionTask executionTask) {
125 String serviceOrderInfoJson = executionTask.getServiceOrderInfoJson();
126 ServiceOrderInfo serviceOrderInfo = null;
129 JsonEntityConverter.convertJsonToServiceOrderInfo(serviceOrderInfoJson);
130 } catch (IOException e) {
132 .error("Unable to read ServiceOrderInfo Json for executionTaskId " + executionTask.getInternalId(), e);
133 throw new TechnicalException(
134 "Unable to read ServiceOrderInfo Json for executionTaskId " + executionTask.getInternalId());
136 return serviceOrderInfo;
140 private void updateServiceOrder(ServiceOrder serviceOrder) {
141 boolean atLeastOneCompleted = false;
142 boolean atLeastOneNotFinished = false;
143 boolean atLeastOneFailed = false;
145 for (ServiceOrderItem serviceOrderItem : serviceOrder.getOrderItem()) {
146 switch (serviceOrderItem.getState()) {
148 atLeastOneCompleted = true;
152 atLeastOneNotFinished = true;
155 atLeastOneFailed = true;
162 if (atLeastOneNotFinished) {
163 serviceOrderService.updateOrderState(serviceOrder, StateType.INPROGRESS);
165 StateType finalState;
166 if (atLeastOneFailed) {
167 if (!atLeastOneCompleted) {
168 finalState = StateType.FAILED;
170 finalState = StateType.PARTIAL;
173 finalState = StateType.COMPLETED;
175 serviceOrderService.updateOrderState(serviceOrder, finalState);
182 * Update ServiceOrderItem with SO response by using serviceOrderRepository with the serviceOrderId
184 private void updateServiceOrderItem(ResponseEntity<CreateServiceInstanceResponse> response,
185 ServiceOrderItem orderItem, ServiceOrder serviceOrder) {
187 if (response == null || !response.getStatusCode().is2xxSuccessful()) {
188 LOGGER.warn("response ko for serviceOrderItem.id=" + orderItem.getId());
189 serviceOrderService.updateOrderItemState(serviceOrder, orderItem, StateType.FAILED);
190 buildOrderMessageIfNeeded(orderItem,serviceOrder,response);
192 CreateServiceInstanceResponse createServiceInstanceResponse = response.getBody();
193 if (createServiceInstanceResponse != null && !orderItem.getState().equals(StateType.FAILED)) {
194 orderItem.getService().setId(createServiceInstanceResponse.getRequestReferences().getInstanceId());
195 orderItem.setRequestId(createServiceInstanceResponse.getRequestReferences().getRequestId());
198 if (!response.getStatusCode().is2xxSuccessful() || response.getBody() == null
199 || response.getBody().getRequestReferences() == null) {
200 serviceOrderService.updateOrderItemState(serviceOrder, orderItem, StateType.FAILED);
202 .warn("order item {} failed , status {} , response {}", orderItem.getId(), response.getStatusCode(),
205 updateOrderItemToInProgress(serviceOrder, orderItem);
211 private void updateOrderItemToInProgress(ServiceOrder serviceOrder, ServiceOrderItem serviceOrderItem){
212 if(serviceOrderItem.getAction()!= ActionType.MODIFY){
213 serviceOrderService.updateOrderItemState(serviceOrder, serviceOrderItem, StateType.INPROGRESS);
215 if(StateType.ACKNOWLEDGED==serviceOrderItem.getState()){
216 serviceOrderService.updateOrderItemState(serviceOrder, serviceOrderItem, StateType.INPROGRESS_MODIFY_REQUEST_DELETE_SEND);
218 serviceOrderService.updateOrderItemState(serviceOrder,serviceOrderItem,StateType.INPROGRESS_MODIFY_REQUEST_CREATE_SEND);
224 private void buildOrderMessageIfNeeded(ServiceOrderItem serviceOrderItem, ServiceOrder serviceOrder,
225 ResponseEntity<?> response) {
228 if(response.getStatusCode()== HttpStatus.INTERNAL_SERVER_ERROR) {
229 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, messageError.getBody().toString());
243 * Update E2EServiceOrderItem with SO response by using serviceOrderRepository with the serviceOrderId
245 private void updateE2EServiceOrderItem(ResponseEntity<CreateE2EServiceInstanceResponse> response,
246 ServiceOrderItem orderItem, ServiceOrder serviceOrder) {
248 if (response == null || !response.getStatusCode().is2xxSuccessful()) {
249 LOGGER.warn("response ko for serviceOrderItem.id=" + orderItem.getId());
250 serviceOrderService.updateOrderItemState(serviceOrder, orderItem, StateType.FAILED);
252 CreateE2EServiceInstanceResponse createE2EServiceInstanceResponse = response.getBody();
253 if (createE2EServiceInstanceResponse != null && !orderItem.getState().equals(StateType.FAILED)) {
254 orderItem.getService().setId(createE2EServiceInstanceResponse.getService().getServiceId());
255 orderItem.setRequestId(createE2EServiceInstanceResponse.getService().getOperationId());
258 if (!response.getStatusCode().is2xxSuccessful() || response.getBody() == null
259 || response.getBody().getService().getOperationId() == null
260 || response.getBody().getService().getServiceId() == null) {
261 serviceOrderService.updateOrderItemState(serviceOrder, orderItem, StateType.FAILED);
263 .warn("order item {} failed , status {} , response {}", orderItem.getId(), response.getStatusCode(),
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.delete(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 {} to failed cause orderitem id {} failed ",
296 taskToDelete.getInternalId(), taskToDelete.getOrderItemId(), executionTask.getOrderItemId());
304 * @param executionTask
307 private List<ExecutionTask> findExecutionTasksRecursively(ExecutionTask executionTask) {
309 List<ExecutionTask> executionTasks = new ArrayList<>();
311 List<ExecutionTask> tasksReliedToAnOrderItemId =
312 executionTaskRepository.findTasksReliedToAnOrderItemId(executionTask.getInternalId());
314 if (CollectionUtils.isEmpty(tasksReliedToAnOrderItemId)) {
315 return Arrays.asList(executionTask);
317 for (ExecutionTask task : tasksReliedToAnOrderItemId) {
318 executionTasks.addAll(findExecutionTasksRecursively(task));
321 executionTasks.add(executionTask);
322 return executionTasks;