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;
21 import org.onap.nbi.apis.serviceorder.SoClient;
22 import org.onap.nbi.apis.serviceorder.model.ServiceCharacteristic;
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.CloudConfiguration;
27 import org.onap.nbi.apis.serviceorder.model.consumer.CreateServiceInstanceResponse;
28 import org.onap.nbi.apis.serviceorder.model.consumer.GetRequestStatusResponse;
29 import org.onap.nbi.apis.serviceorder.model.consumer.MSOPayload;
30 import org.onap.nbi.apis.serviceorder.model.consumer.ModelInfo;
31 import org.onap.nbi.apis.serviceorder.model.consumer.OwningEntity;
32 import org.onap.nbi.apis.serviceorder.model.consumer.Project;
33 import org.onap.nbi.apis.serviceorder.model.consumer.RequestDetails;
34 import org.onap.nbi.apis.serviceorder.model.consumer.RequestInfo;
35 import org.onap.nbi.apis.serviceorder.model.consumer.RequestParameters;
36 import org.onap.nbi.apis.serviceorder.model.consumer.RequestState;
37 import org.onap.nbi.apis.serviceorder.model.consumer.SubscriberInfo;
38 import org.onap.nbi.apis.serviceorder.model.consumer.UserParams;
39 import org.onap.nbi.apis.serviceorder.model.orchestrator.ExecutionTask;
40 import org.onap.nbi.apis.serviceorder.model.orchestrator.ServiceOrderInfo;
41 import org.onap.nbi.apis.serviceorder.repositories.ExecutionTaskRepository;
42 import org.onap.nbi.apis.serviceorder.service.ServiceOrderService;
43 import org.onap.nbi.apis.serviceorder.utils.JsonEntityConverter;
44 import org.onap.nbi.exceptions.TechnicalException;
45 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory;
47 import org.springframework.beans.factory.annotation.Autowired;
48 import org.springframework.beans.factory.annotation.Value;
49 import org.springframework.http.ResponseEntity;
50 import org.springframework.stereotype.Service;
51 import org.springframework.util.CollectionUtils;
54 public class SOTaskProcessor {
56 @Value("${nbi.callForVNF}")
57 private boolean enableCallForVNF;
59 @Value("${onap.lcpCloudRegionId}")
60 private String lcpCloudRegionId;
62 @Value("${onap.tenantId}")
63 private String tenantId;
65 @Value("${so.owning.entity.id}")
66 private String soOwningEntityId;
68 @Value("${so.owning.entity.name}")
69 private String soOwningEntityName;
71 @Value("${so.project.name}")
72 private String soProjectName;
76 private ServiceOrderService serviceOrderService;
79 private ExecutionTaskRepository executionTaskRepository;
82 private SoClient soClient;
85 private static final Logger LOGGER = LoggerFactory.getLogger(SOTaskProcessor.class);
88 * Run the ServiceOrchestrator processing for a serviceOrderItem which with any sub relations
90 * @throws InterruptedException
92 public void processOrderItem(ExecutionTask executionTask) throws InterruptedException {
94 ServiceOrderInfo serviceOrderInfo = getServiceOrderInfo(executionTask);
96 ServiceOrder serviceOrder = serviceOrderService.findServiceOrderById(serviceOrderInfo.getServiceOrderId());
97 ServiceOrderItem serviceOrderItem = getServiceOrderItem(executionTask, serviceOrder);
99 if (StateType.ACKNOWLEDGED == serviceOrderItem.getState()) {
101 ResponseEntity<CreateServiceInstanceResponse> response = postServiceOrderItem(serviceOrderInfo,
103 updateServiceOrderItem(response, serviceOrderItem,serviceOrder);
106 if (executionTask.getNbRetries() > 0 && StateType.FAILED != serviceOrderItem.getState()
108 // TODO lancer en asynchrone
109 pollSoRequestStatus(serviceOrder,serviceOrderItem);
110 if (serviceOrderItem.getState().equals(StateType.COMPLETED)) {
111 updateSuccessTask(executionTask);
113 int nbRetries = executionTask.getNbRetries();
114 executionTask.setNbRetries(--nbRetries);
115 executionTask.setLastAttemptDate(new Date());
116 executionTaskRepository.save(executionTask);
119 updateFailedTask(executionTask, serviceOrder);
122 updateServiceOrder(serviceOrder);
125 private ResponseEntity<CreateServiceInstanceResponse> postServiceOrderItem(ServiceOrderInfo serviceOrderInfo,
126 ServiceOrderItem serviceOrderItem) {
127 ResponseEntity<CreateServiceInstanceResponse> response = null;
129 response = postSORequest(serviceOrderItem, serviceOrderInfo);
130 } catch (NullPointerException e) {
131 LOGGER.error("Unable to create service instance for serviceOrderItem.id=" + serviceOrderItem.getId(), e);
137 private ServiceOrderItem getServiceOrderItem(ExecutionTask executionTask, ServiceOrder serviceOrder) {
138 for (ServiceOrderItem item : serviceOrder.getOrderItem()) {
139 if (item.getId().equals(executionTask.getOrderItemId())) {
143 throw new TechnicalException(
144 "Unable to retrieve serviceOrderItem forexecutionTaskId " + executionTask.getInternalId());
147 private ServiceOrderInfo getServiceOrderInfo(ExecutionTask executionTask) {
148 String serviceOrderInfoJson = executionTask.getServiceOrderInfoJson();
149 ServiceOrderInfo serviceOrderInfo = null;
152 JsonEntityConverter.convertJsonToServiceOrderInfo(serviceOrderInfoJson);
153 } catch (IOException e) {
155 .error("Unable to read ServiceOrderInfo Json for executionTaskId " + executionTask.getInternalId(), e);
156 throw new TechnicalException(
157 "Unable to read ServiceOrderInfo Json for executionTaskId " + executionTask.getInternalId());
159 return serviceOrderInfo;
162 private ResponseEntity<CreateServiceInstanceResponse> postSORequest(ServiceOrderItem serviceOrderItem,
163 ServiceOrderInfo serviceOrderInfo) {
164 RequestDetails requestDetails = buildSoRequest(serviceOrderItem,
165 serviceOrderInfo.getServiceOrderItemInfos().get(serviceOrderItem.getId()).getCatalogResponse(),
166 serviceOrderInfo.getSubscriberInfo());
167 MSOPayload msoPayload = new MSOPayload(requestDetails);
168 ResponseEntity<CreateServiceInstanceResponse> response = null;
170 switch (serviceOrderItem.getAction()) {
172 response = soClient.callCreateServiceInstance(msoPayload);
175 response = soClient.callDeleteServiceInstance(msoPayload, serviceOrderItem.getService().getId());
183 private void updateServiceOrder(ServiceOrder serviceOrder) {
184 boolean atLeastOneCompleted = false;
185 boolean atLeastOneNotFinished = false;
186 boolean atLeastOneFailed = false;
188 for (ServiceOrderItem serviceOrderItem : serviceOrder.getOrderItem()) {
189 switch (serviceOrderItem.getState()) {
191 atLeastOneCompleted = true;
195 atLeastOneNotFinished = true;
198 atLeastOneFailed = true;
206 if (atLeastOneNotFinished) {
207 serviceOrderService.updateOrderState(serviceOrder,StateType.INPROGRESS);
209 StateType finalState;
210 if (atLeastOneFailed) {
211 if (!atLeastOneCompleted) {
212 finalState=StateType.FAILED;
214 finalState=StateType.PARTIAL;
217 finalState=StateType.COMPLETED;
219 serviceOrderService.updateOrderFinalState(serviceOrder,finalState);
227 private void pollSoRequestStatus(ServiceOrder serviceOrder,
228 ServiceOrderItem orderItem) throws InterruptedException {
229 boolean stopPolling = false;
230 String requestId = orderItem.getRequestId();
231 GetRequestStatusResponse response = null;
234 while (!stopPolling) {
235 response = soClient.callGetRequestStatus(requestId);
236 if (response != null) {
237 if (response.getRequest().getRequestStatus().getPercentProgress() != 100) {
239 serviceOrderService.updateOrderItemState(serviceOrder,orderItem,StateType.INPROGRESS);
241 LOGGER.debug("orderitem id {} still in progress from so",orderItem.getId());
242 } else if (RequestState.COMPLETE != response.getRequest().getRequestStatus().getRequestState()) {
243 serviceOrderService.updateOrderItemState(serviceOrder,orderItem,StateType.FAILED);
245 LOGGER.debug("orderitem id {} failed, response from request status {}",orderItem.getId(),response.getRequest().getRequestStatus().getRequestState());
247 serviceOrderService.updateOrderItemState(serviceOrder,orderItem,StateType.COMPLETED);
249 LOGGER.debug("orderitem id {} completed");
252 serviceOrderService.updateOrderItemState(serviceOrder,orderItem,StateType.INPROGRESS);
254 LOGGER.debug("orderitem id {} still in progress from so",orderItem.getId());
256 if (nbRetries == 3) {
258 LOGGER.debug("orderitem id {} stop polling from getrequeststatus, 3 retries done",orderItem.getId());
265 * Build SO CREATE request from the ServiceOrder and catalog informations from SDC
269 * @param subscriberInfo
272 private RequestDetails buildSoRequest(ServiceOrderItem orderItem, Map<String, Object> sdcInfos,
273 SubscriberInfo subscriberInfo) {
274 RequestDetails requestDetails = new RequestDetails();
276 requestDetails.setSubscriberInfo(subscriberInfo);
278 ModelInfo modelInfo = new ModelInfo();
279 modelInfo.setModelType("service");
280 modelInfo.setModelInvariantId((String) sdcInfos.get("invariantUUID"));
281 modelInfo.setModelNameVersionId(orderItem.getService().getServiceSpecification().getId());
282 modelInfo.setModelVersionId(orderItem.getService().getServiceSpecification().getId());
283 modelInfo.setModelName((String) sdcInfos.get("name"));
284 modelInfo.setModelVersion((String) sdcInfos.get("version"));
285 requestDetails.setModelInfo(modelInfo);
287 RequestInfo requestInfo = new RequestInfo();
288 requestInfo.setInstanceName(orderItem.getService().getName());
289 requestInfo.setSource("VID");
290 requestInfo.setSuppressRollback(false);
291 requestInfo.setRequestorId("NBI");
292 requestDetails.setRequestInfo(requestInfo);
294 RequestParameters requestParameters = new RequestParameters();
295 requestParameters.setSubscriptionServiceType((String) sdcInfos.get("name"));
296 requestParameters.setUserParams(
297 retrieveUserParamsFromServiceCharacteristics(orderItem.getService().getServiceCharacteristic()));
298 requestParameters.setaLaCarte(true);
299 requestDetails.setRequestParameters(requestParameters);
301 CloudConfiguration cloudConfiguration = new CloudConfiguration(lcpCloudRegionId, tenantId);
302 requestDetails.setCloudConfiguration(cloudConfiguration);
304 OwningEntity owningEntity = new OwningEntity();
305 owningEntity.setOwningEntityId(soOwningEntityId);
306 owningEntity.setOwningEntityName(soOwningEntityName);
307 requestDetails.setOwningEntity(owningEntity);
309 Project project = new Project();
310 project.setProjectName(soProjectName);
312 requestDetails.setProject(project);
314 return requestDetails;
318 * Build a list of UserParams for the SO request by browsing a list of ServiceCharacteristics from SDC
320 private List<UserParams> retrieveUserParamsFromServiceCharacteristics(List<ServiceCharacteristic> characteristics) {
321 List<UserParams> userParams = new ArrayList<>();
323 if (!CollectionUtils.isEmpty(characteristics)) {
324 for (ServiceCharacteristic characteristic : characteristics) {
325 UserParams userParam = new UserParams(characteristic.getName(),
326 characteristic.getValue().getServiceCharacteristicValue());
327 userParams.add(userParam);
336 * Update ServiceOrderItem with SO response by using serviceOrderRepository with the serviceOrderId
339 * @param serviceOrder
341 private void updateServiceOrderItem(ResponseEntity<CreateServiceInstanceResponse> response,
342 ServiceOrderItem orderItem, ServiceOrder serviceOrder) {
344 if (response == null) {
345 LOGGER.warn("response=null for serviceOrderItem.id=" + orderItem.getId());
346 serviceOrderService.updateOrderItemState(serviceOrder,orderItem,StateType.FAILED);
349 CreateServiceInstanceResponse createServiceInstanceResponse = response.getBody();
350 if (createServiceInstanceResponse != null && !orderItem.getState().equals(StateType.FAILED)) {
351 orderItem.getService().setId(createServiceInstanceResponse.getRequestReferences().getInstanceId());
352 orderItem.setRequestId(createServiceInstanceResponse.getRequestReferences().getRequestId());
355 if (!response.getStatusCode().is2xxSuccessful() || response.getBody() == null
356 || response.getBody().getRequestReferences() == null) {
357 serviceOrderService.updateOrderItemState(serviceOrder,orderItem,StateType.FAILED);
358 LOGGER.warn("order item {} failed , status {} , response {}",orderItem.getId(),response.getStatusCode(),response.getBody());
360 serviceOrderService.updateOrderItemState(serviceOrder,orderItem,StateType.INPROGRESS);
366 * Update an executionTask in database when it's process with a success
368 * @param executionTask
370 private void updateSuccessTask(ExecutionTask executionTask) {
371 executionTaskRepository.delete(executionTask.getInternalId());
372 executionTaskRepository.updateReliedTaskAfterDelete(executionTask.getInternalId());
377 * @param executionTask
378 * @param serviceOrder
380 private void updateFailedTask(ExecutionTask executionTask, ServiceOrder serviceOrder) {
381 List<ExecutionTask> executionTasksToDelete = findExecutionTasksRecursively(executionTask);
382 for (ExecutionTask taskId : executionTasksToDelete) {
383 executionTaskRepository.delete(taskId);
384 LOGGER.warn("task {} with orderitem id {} deleted cause orderitem id {} failed ",taskId.getInternalId(),taskId.getOrderItemId(),executionTask.getOrderItemId());
386 for (ServiceOrderItem item : serviceOrder.getOrderItem()) {
387 for (ExecutionTask taskToDelete : executionTasksToDelete) {
388 if (taskToDelete.getOrderItemId().equals(item.getId())) {
389 serviceOrderService.updateOrderItemState(serviceOrder,item,StateType.FAILED);
390 LOGGER.warn("task {} with orderitem id {} to failed cause orderitem id {} failed ",taskToDelete.getInternalId(),taskToDelete.getOrderItemId(),executionTask.getOrderItemId());
398 * @param executionTask
401 private List<ExecutionTask> findExecutionTasksRecursively(ExecutionTask executionTask) {
403 List<ExecutionTask> executionTasks = new ArrayList<>();
405 List<ExecutionTask> tasksReliedToAnOrderItemId =
406 executionTaskRepository.findTasksReliedToAnOrderItemId(executionTask.getInternalId());
408 if (CollectionUtils.isEmpty(tasksReliedToAnOrderItemId)) {
409 return Arrays.asList(executionTask);
411 for (ExecutionTask task : tasksReliedToAnOrderItemId) {
412 executionTasks.addAll(findExecutionTasksRecursively(task));
415 executionTasks.add(executionTask);
416 return executionTasks;