/**
* Copyright (c) 2018 Orange
*
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
- * in compliance with the License. You may obtain a copy of the License at
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
- * Unless required by applicable law or agreed to in writing, software distributed under the License
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the License for the specific language governing permissions and limitations under
- * the License.
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
+ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations under the License.
*/
+
package org.onap.nbi.apis.serviceorder.workflow;
-import org.onap.nbi.apis.serviceorder.SoClient;
-import org.onap.nbi.apis.serviceorder.model.ServiceCharacteristic;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+import java.util.Optional;
+import org.onap.nbi.apis.serviceorder.model.ActionType;
import org.onap.nbi.apis.serviceorder.model.ServiceOrder;
import org.onap.nbi.apis.serviceorder.model.ServiceOrderItem;
import org.onap.nbi.apis.serviceorder.model.StateType;
-import org.onap.nbi.apis.serviceorder.model.consumer.*;
+import org.onap.nbi.apis.serviceorder.model.consumer.CreateE2EServiceInstanceResponse;
+import org.onap.nbi.apis.serviceorder.model.consumer.CreateServiceInstanceResponse;
import org.onap.nbi.apis.serviceorder.model.orchestrator.ExecutionTask;
import org.onap.nbi.apis.serviceorder.model.orchestrator.ServiceOrderInfo;
-import org.onap.nbi.apis.serviceorder.model.orchestrator.ServiceOrderInfoJson;
import org.onap.nbi.apis.serviceorder.repositories.ExecutionTaskRepository;
-import org.onap.nbi.apis.serviceorder.repositories.ServiceOrderRepository;
+import org.onap.nbi.apis.serviceorder.service.ServiceOrderService;
+import org.onap.nbi.apis.serviceorder.utils.E2EServiceUtils;
import org.onap.nbi.apis.serviceorder.utils.JsonEntityConverter;
+import org.onap.nbi.apis.serviceorder.utils.MacroServiceUtils;
+import org.onap.nbi.exceptions.TechnicalException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
-import java.io.IOException;
-import java.util.*;
-
@Service
public class SOTaskProcessor {
- @Value("${nbi.callForVNF}")
- private boolean enableCallForVNF;
-
- @Value("${onap.lcpCloudRegionId}")
- private String lcpCloudRegionId;
-
- @Value("${onap.tenantId}")
- private String tenantId;
-
@Autowired
- private ServiceOrderRepository serviceOrderRepository;
+ private ServiceOrderService serviceOrderService;
@Autowired
private ExecutionTaskRepository executionTaskRepository;
@Autowired
- private SoClient soClient;
+ private PostSoProcessor postSoProcessor;
+ @Autowired
+ private SOGetStatusManager sOGetStatusManager;
+
+ @Value("${scheduler.pollingDurationInMins}")
+ private float pollingDurationInMins;
private static final Logger LOGGER = LoggerFactory.getLogger(SOTaskProcessor.class);
/**
* Run the ServiceOrchestrator processing for a serviceOrderItem which with any sub relations
- *
- * @throws InterruptedException
*/
- public void processOrderItem(ExecutionTask executionTask) throws InterruptedException {
+ public void processOrderItem(ExecutionTask executionTask) {
+ executionTask.setLastAttemptDate(new Date());
+ executionTaskRepository.save(executionTask);
- ServiceOrderInfoJson serviceOrderInfoJson = executionTask.getServiceOrderInfoJson();
- ServiceOrder serviceOrder = serviceOrderRepository.findOne(serviceOrderInfoJson.getServiceOrderId());
- ServiceOrderItem serviceOrderItem = null;
- for (ServiceOrderItem item : serviceOrder.getOrderItem()) {
- if (item.getId().equals(executionTask.getOrderItemId())) {
- serviceOrderItem = item;
- }
- }
+ ServiceOrderInfo serviceOrderInfo = getServiceOrderInfo(executionTask);
- ServiceOrderInfo serviceOrderInfo = null;
- try {
- serviceOrderInfo =
- JsonEntityConverter.convertJsonToServiceOrderInfo(serviceOrderInfoJson.getServiceOrderInfoJson());
- } catch (IOException e) {
- LOGGER.warn("Unable to read ServiceOrderInfo Json for serviceOrderId " + serviceOrder.getId(), e);
+ Optional<ServiceOrder> optionalServiceOrder =
+ serviceOrderService.findServiceOrderById(serviceOrderInfo.getServiceOrderId());
+ if (!optionalServiceOrder.isPresent()) {
+ throw new TechnicalException(
+ "Unable to retrieve service order for id " + serviceOrderInfo.getServiceOrderId());
}
+ ServiceOrder serviceOrder = optionalServiceOrder.get();
+ ServiceOrderItem serviceOrderItem = getServiceOrderItem(executionTask, serviceOrder);
+ boolean e2eService =
+ E2EServiceUtils.isE2EService(serviceOrderInfo.getServiceOrderItemInfos().get(serviceOrderItem.getId()));
+ boolean macroService = MacroServiceUtils
+ .isMacroService(serviceOrderInfo.getServiceOrderItemInfos().get(serviceOrderItem.getId()));
+
+ if (shouldPostSo(serviceOrderItem)) {
+ if (e2eService) {
+ ResponseEntity<CreateE2EServiceInstanceResponse> response =
+ postSoProcessor.postE2EServiceOrderItem(serviceOrderInfo, serviceOrderItem, serviceOrder);
+ updateE2EServiceOrderItem(response, serviceOrderItem, serviceOrder);
+ } else if (macroService) {
+ LOGGER.info("Mode type macro");
+ //TODO: Add logic to construct SO macro request body and call SO macro flow.(EXTAPI-368)
- if (serviceOrderItem != null && StateType.ACKNOWLEDGED == serviceOrderItem.getState()) {
-
- ResponseEntity<CreateServiceInstanceResponse> response = null;
- try {
- response = postSORequest(serviceOrderItem, serviceOrderInfo);
- } catch (NullPointerException e) {
- LOGGER.warn("Enable to create service instance for serviceOrderItem.id=" + serviceOrderItem.getId(), e);
- response = null;
- }
-
- if (response == null) {
- LOGGER.warn("response=null for serviceOrderItem.id=" + serviceOrderItem.getId());
- serviceOrderItem.setState(StateType.FAILED);
} else {
- updateServiceOrderItem(response.getBody(), serviceOrderItem);
- if (response.getStatusCode() != HttpStatus.CREATED || response.getBody() == null
- || response.getBody().getRequestReference() == null) {
- serviceOrderItem.setState(StateType.FAILED);
- } else {
- serviceOrderItem.setState(StateType.INPROGRESS);
- }
+ ResponseEntity<CreateServiceInstanceResponse> response =
+ postSoProcessor.postServiceOrderItem(serviceOrderInfo, serviceOrderItem);
+ updateServiceOrderItem(response, serviceOrderItem, serviceOrder);
}
}
- if (executionTask.getNbRetries() > 0) {
+ boolean shouldStopPolling = shouldStopPolling(executionTask);
+ if (!shouldStopPolling && StateType.FAILED != serviceOrderItem.getState()) {
// TODO lancer en asynchrone
- pollSoRequestStatus(serviceOrderItem);
+ sOGetStatusManager.pollRequestStatus(serviceOrder, serviceOrderItem, e2eService);
+
if (serviceOrderItem.getState().equals(StateType.COMPLETED)) {
updateSuccessTask(executionTask);
- } else {
- int nbRetries = executionTask.getNbRetries();
- executionTask.setNbRetries(--nbRetries);
- executionTask.setLastAttemptDate(new Date());
- executionTaskRepository.save(executionTask);
}
+ } else if (shouldStopPolling && StateType.FAILED != serviceOrderItem.getState()) {
+ serviceOrderService.addOrderItemMessage(serviceOrder, serviceOrderItem, "504");
+ updateFailedTask(executionTask, serviceOrder);
} else {
updateFailedTask(executionTask, serviceOrder);
}
-
updateServiceOrder(serviceOrder);
}
- private ResponseEntity<CreateServiceInstanceResponse> postSORequest(ServiceOrderItem serviceOrderItem,
- ServiceOrderInfo serviceOrderInfo) {
- RequestDetails requestDetails = buildSoRequest(serviceOrderItem,
- serviceOrderInfo.getServiceOrderItemInfos().get(serviceOrderItem.getId()).getCatalogResponse(),
- serviceOrderInfo.getSubscriberInfo());
- MSOPayload msoPayload = new MSOPayload(requestDetails);
- ResponseEntity<CreateServiceInstanceResponse> response = null;
-
- switch (serviceOrderItem.getAction()) {
- case ADD:
- response = soClient.callCreateServiceInstance(msoPayload);
- break;
- case DELETE:
- response = soClient.callDeleteServiceInstance(msoPayload, serviceOrderItem.getService().getId());
- break;
- default:
- break;
+ private boolean shouldPostSo(ServiceOrderItem serviceOrderItem) {
+ return StateType.ACKNOWLEDGED == serviceOrderItem.getState()
+ || StateType.INPROGRESS_MODIFY_ITEM_TO_CREATE == serviceOrderItem.getState();
+ }
+
+ private ServiceOrderItem getServiceOrderItem(ExecutionTask executionTask, ServiceOrder serviceOrder) {
+ for (ServiceOrderItem item : serviceOrder.getOrderItem()) {
+ if (item.getId().equals(executionTask.getOrderItemId())) {
+ return item;
+ }
+ }
+ throw new TechnicalException(
+ "Unable to retrieve serviceOrderItem for executionTaskId " + executionTask.getInternalId());
+ }
+
+ private ServiceOrderInfo getServiceOrderInfo(ExecutionTask executionTask) {
+ String serviceOrderInfoJson = executionTask.getServiceOrderInfoJson();
+ ServiceOrderInfo serviceOrderInfo = null;
+ try {
+ serviceOrderInfo = JsonEntityConverter.convertJsonToServiceOrderInfo(serviceOrderInfoJson);
+ } catch (IOException e) {
+ LOGGER.error("Unable to read ServiceOrderInfo Json for executionTaskId " + executionTask.getInternalId(),
+ e);
+ throw new TechnicalException(
+ "Unable to read ServiceOrderInfo Json for executionTaskId " + executionTask.getInternalId());
}
- return response;
+ return serviceOrderInfo;
}
private void updateServiceOrder(ServiceOrder serviceOrder) {
boolean atLeastOneNotFinished = false;
boolean atLeastOneFailed = false;
-
for (ServiceOrderItem serviceOrderItem : serviceOrder.getOrderItem()) {
switch (serviceOrderItem.getState()) {
case COMPLETED:
}
}
-
if (atLeastOneNotFinished) {
- serviceOrder.setState(StateType.INPROGRESS);
+ serviceOrderService.updateOrderState(serviceOrder, StateType.INPROGRESS);
} else {
- serviceOrder.setCompletionDateTime(new Date());
+ StateType finalState;
if (atLeastOneFailed) {
if (!atLeastOneCompleted) {
- serviceOrder.setState(StateType.FAILED);
+ finalState = StateType.FAILED;
} else {
- serviceOrder.setState(StateType.PARTIAL);
+ finalState = StateType.PARTIAL;
}
} else {
- serviceOrder.setState(StateType.COMPLETED);
+ finalState = StateType.COMPLETED;
}
+ serviceOrderService.updateOrderState(serviceOrder, finalState);
}
- serviceOrderRepository.save(serviceOrder);
}
-
/**
- * * @param orderItem
- *
- * @throws InterruptedException
+ * Update ServiceOrderItem with SO response by using serviceOrderRepository with the serviceOrderId
*/
- private void pollSoRequestStatus(ServiceOrderItem orderItem) throws InterruptedException {
- boolean stopPolling = false;
- String requestId = orderItem.getRequestId();
- GetRequestStatusResponse response = null;
- int nbRetries = 0;
-
- while (!stopPolling) {
- response = soClient.callGetRequestStatus(requestId);
- if (response != null) {
- if (response.getRequest().getRequestStatus().getPercentProgress() != 100) {
- nbRetries++;
- orderItem.setState(StateType.INPROGRESS);
- Thread.sleep(1000);
- } else if (RequestState.COMPLETE != response.getRequest().getRequestStatus().getRequestState()) {
- orderItem.setState(StateType.FAILED);
- stopPolling = true;
- } else {
- orderItem.setState(StateType.COMPLETED);
- stopPolling = true;
- }
- } else {
- orderItem.setState(StateType.INPROGRESS);
- stopPolling = true;
+ private void updateServiceOrderItem(ResponseEntity<CreateServiceInstanceResponse> response,
+ ServiceOrderItem orderItem, ServiceOrder serviceOrder) {
+
+ if (response == null || !response.getStatusCode().is2xxSuccessful()) {
+ LOGGER.warn("response ko for serviceOrderItem.id=" + orderItem.getId());
+ serviceOrderService.updateOrderItemState(serviceOrder, orderItem, StateType.FAILED);
+ buildOrderMessageIfNeeded(orderItem, serviceOrder, response);
+ } else {
+ CreateServiceInstanceResponse createServiceInstanceResponse = response.getBody();
+ if (createServiceInstanceResponse != null && !orderItem.getState().equals(StateType.FAILED)) {
+ orderItem.getService().setId(createServiceInstanceResponse.getRequestReferences().getInstanceId());
+ orderItem.setRequestId(createServiceInstanceResponse.getRequestReferences().getRequestId());
}
- if (nbRetries == 3) {
- stopPolling = true;
+
+ if (!response.getStatusCode().is2xxSuccessful() || response.getBody() == null
+ || response.getBody().getRequestReferences() == null) {
+ serviceOrderService.updateOrderItemState(serviceOrder, orderItem, StateType.FAILED);
+ LOGGER.warn("order item {} failed , status {} , response {}", orderItem.getId(),
+ response.getStatusCode(), response.getBody());
+ } else {
+ updateOrderItemToInProgress(serviceOrder, orderItem);
}
}
}
- /**
- * Build SO CREATE request from the ServiceOrder and catalog informations from SDC
- *
- * @param orderItem
- * @param sdcInfos
- * @param subscriberInfo
- * @return
- */
- private RequestDetails buildSoRequest(ServiceOrderItem orderItem, LinkedHashMap<String, Object> sdcInfos,
- SubscriberInfo subscriberInfo) {
- RequestDetails requestDetails = new RequestDetails();
-
- requestDetails.setSubscriberInfo(subscriberInfo);
-
- ModelInfo modelInfo = new ModelInfo();
- modelInfo.setModelType("service");
- modelInfo.setModelInvariantId((String) sdcInfos.get("invariantUUID"));
- modelInfo.setModelNameVersionId(orderItem.getService().getServiceSpecification().getId());
- modelInfo.setModelName((String) sdcInfos.get("name"));
- modelInfo.setModelVersion((String) sdcInfos.get("version"));
- requestDetails.setModelInfo(modelInfo);
-
- RequestInfo requestInfo = new RequestInfo();
- requestInfo.setInstanceName(orderItem.getService().getName());
- requestInfo.setSource("VID");
- requestInfo.setSuppressRollback(false);
- requestInfo.setRequestorId("NBI");
- requestDetails.setRequestInfo(requestInfo);
-
- RequestParameters requestParameters = new RequestParameters();
- requestParameters.setSubscriptionServiceType((String) sdcInfos.get("name"));
- requestParameters.setUserParams(
- retrieveUserParamsFromServiceCharacteristics(orderItem.getService().getServiceCharacteristic()));
- requestParameters.setaLaCarte(true);
- requestDetails.setRequestParameters(requestParameters);
-
- CloudConfiguration cloudConfiguration = new CloudConfiguration(lcpCloudRegionId, tenantId);
- requestDetails.setCloudConfiguration(cloudConfiguration);
- return requestDetails;
+ private void updateOrderItemToInProgress(ServiceOrder serviceOrder, ServiceOrderItem serviceOrderItem) {
+ if (serviceOrderItem.getAction() != ActionType.MODIFY) {
+ serviceOrderService.updateOrderItemState(serviceOrder, serviceOrderItem, StateType.INPROGRESS);
+ } else {
+ if (StateType.ACKNOWLEDGED == serviceOrderItem.getState()) {
+ serviceOrderService.updateOrderItemState(serviceOrder, serviceOrderItem,
+ StateType.INPROGRESS_MODIFY_REQUEST_DELETE_SEND);
+ } else {
+ serviceOrderService.updateOrderItemState(serviceOrder, serviceOrderItem,
+ StateType.INPROGRESS_MODIFY_REQUEST_CREATE_SEND);
+ }
+ }
}
- /**
- * Build a list of UserParams for the SO request by browsing a list of ServiceCharacteristics from
- * SDC
- *
- * @param characteristics
- * @return
- */
- private List<UserParams> retrieveUserParamsFromServiceCharacteristics(List<ServiceCharacteristic> characteristics) {
- List<UserParams> userParams = new ArrayList<UserParams>();
-
- if (!CollectionUtils.isEmpty(characteristics)) {
- for (ServiceCharacteristic characteristic : characteristics) {
- UserParams userParam = new UserParams(characteristic.getName(),
- characteristic.getValue().getServiceCharacteristicValue());
- userParams.add(userParam);
+ private void buildOrderMessageIfNeeded(ServiceOrderItem serviceOrderItem, ServiceOrder serviceOrder,
+ ResponseEntity<?> response) {
+ if (response != null) {
+ if (response.getStatusCode() == HttpStatus.INTERNAL_SERVER_ERROR) {
+ serviceOrderService.addOrderMessage(serviceOrder, "502");
+ } else if (response.getStatusCode() == HttpStatus.BAD_REQUEST) {
+ ResponseEntity<?> messageError = response;
+ if (messageError.getBody().toString().toLowerCase().contains("serviceinstance already exists")) {
+ serviceOrderService.addOrderItemMessage(serviceOrder, serviceOrderItem, "105");
+ } else {
+ serviceOrderService.addOrderItemMessageRequestSo(serviceOrder, serviceOrderItem,
+ messageError.getBody().toString());
+ }
}
}
-
- return userParams;
}
-
/**
- * Update ServiceOrderItem with SO response by using serviceOrderRepository with the serviceOrderId
- *
- * @param createServiceInstanceResponse
- * @param orderItem
+ * Update E2EServiceOrderItem with SO response by using serviceOrderRepository with the serviceOrderId
*/
- private void updateServiceOrderItem(CreateServiceInstanceResponse createServiceInstanceResponse,
- ServiceOrderItem orderItem) {
+ private void updateE2EServiceOrderItem(ResponseEntity<CreateE2EServiceInstanceResponse> response,
+ ServiceOrderItem orderItem, ServiceOrder serviceOrder) {
+
+ if (response == null || !response.getStatusCode().is2xxSuccessful()) {
+ LOGGER.warn("response ko for serviceOrderItem.id=" + orderItem.getId());
+ serviceOrderService.updateOrderItemState(serviceOrder, orderItem, StateType.FAILED);
+ } else {
+ CreateE2EServiceInstanceResponse createE2EServiceInstanceResponse = response.getBody();
+ if (createE2EServiceInstanceResponse != null && !orderItem.getState().equals(StateType.FAILED)) {
+ orderItem.getService().setId(createE2EServiceInstanceResponse.getService().getServiceId());
+ orderItem.setRequestId(createE2EServiceInstanceResponse.getService().getOperationId());
+ }
- if (createServiceInstanceResponse != null && !orderItem.getState().equals(StateType.FAILED)) {
- orderItem.getService().setId(createServiceInstanceResponse.getRequestReference().getInstanceId());
- orderItem.setRequestId(createServiceInstanceResponse.getRequestReference().getRequestId());
+ if (!response.getStatusCode().is2xxSuccessful() || response.getBody() == null
+ || response.getBody().getService().getOperationId() == null
+ || response.getBody().getService().getServiceId() == null) {
+ serviceOrderService.updateOrderItemState(serviceOrder, orderItem, StateType.FAILED);
+ LOGGER.warn("order item {} failed , status {} , response {}", orderItem.getId(),
+ response.getStatusCode(), response.getBody());
+ } else {
+ serviceOrderService.updateOrderItemState(serviceOrder, orderItem, StateType.INPROGRESS);
+ }
}
}
/**
* Update an executionTask in database when it's process with a success
- *
- * @param executionTask
*/
private void updateSuccessTask(ExecutionTask executionTask) {
- executionTaskRepository.delete(executionTask.getInternalId());
+ executionTaskRepository.deleteById(executionTask.getInternalId());
executionTaskRepository.updateReliedTaskAfterDelete(executionTask.getInternalId());
+
}
/**
List<ExecutionTask> executionTasksToDelete = findExecutionTasksRecursively(executionTask);
for (ExecutionTask taskId : executionTasksToDelete) {
executionTaskRepository.delete(taskId);
+ LOGGER.warn("task {} with orderitem id {} deleted cause orderitem id {} failed ", taskId.getInternalId(),
+ taskId.getOrderItemId(), executionTask.getOrderItemId());
}
-
for (ServiceOrderItem item : serviceOrder.getOrderItem()) {
for (ExecutionTask taskToDelete : executionTasksToDelete) {
if (taskToDelete.getOrderItemId().equals(item.getId())) {
- item.setState(StateType.FAILED);
+ serviceOrderService.updateOrderItemState(serviceOrder, item, StateType.FAILED);
+ LOGGER.warn("task {} with orderitem id {} failed cause orderitem id {} failed ",
+ taskToDelete.getInternalId(), taskToDelete.getOrderItemId(),
+ executionTask.getOrderItemId());
+
}
}
}
return executionTasks;
}
-
+ private boolean shouldStopPolling(ExecutionTask executionTask) {
+ long createTimeinMillis = executionTask.getCreateDate().getTime();
+ long lastAttemptTimeInMillis = executionTask.getLastAttemptDate().getTime();
+ long differenceInMillis = lastAttemptTimeInMillis - createTimeinMillis;
+ float pollingDurationInMillis = pollingDurationInMins * 60000;
+ LOGGER.debug("Task {} with orderitem id {}: Task create date: {} Task last attempt date: {}",
+ executionTask.getInternalId(), executionTask.getOrderItemId(), createTimeinMillis,
+ lastAttemptTimeInMillis);
+ LOGGER.debug("Difference {} and Polling Duration {}", differenceInMillis, pollingDurationInMins);
+ return (differenceInMillis > pollingDurationInMillis);
+ }
}