2 * Copyright (c) 2018 Orange
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 * in compliance with 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
10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 * or implied. See the License for the specific language governing permissions and limitations under
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.LinkedHashMap;
21 import java.util.List;
22 import org.onap.nbi.apis.serviceorder.SoClient;
23 import org.onap.nbi.apis.serviceorder.model.ServiceCharacteristic;
24 import org.onap.nbi.apis.serviceorder.model.ServiceOrder;
25 import org.onap.nbi.apis.serviceorder.model.ServiceOrderItem;
26 import org.onap.nbi.apis.serviceorder.model.StateType;
27 import org.onap.nbi.apis.serviceorder.model.consumer.CloudConfiguration;
28 import org.onap.nbi.apis.serviceorder.model.consumer.CreateServiceInstanceResponse;
29 import org.onap.nbi.apis.serviceorder.model.consumer.GetRequestStatusResponse;
30 import org.onap.nbi.apis.serviceorder.model.consumer.ModelInfo;
31 import org.onap.nbi.apis.serviceorder.model.consumer.RequestDetails;
32 import org.onap.nbi.apis.serviceorder.model.consumer.RequestInfo;
33 import org.onap.nbi.apis.serviceorder.model.consumer.RequestParameters;
34 import org.onap.nbi.apis.serviceorder.model.consumer.RequestState;
35 import org.onap.nbi.apis.serviceorder.model.consumer.SubscriberInfo;
36 import org.onap.nbi.apis.serviceorder.model.consumer.UserParams;
37 import org.onap.nbi.apis.serviceorder.model.orchestrator.ExecutionTask;
38 import org.onap.nbi.apis.serviceorder.model.orchestrator.ServiceOrderInfo;
39 import org.onap.nbi.apis.serviceorder.model.orchestrator.ServiceOrderInfoJson;
40 import org.onap.nbi.apis.serviceorder.repositories.ExecutionTaskRepository;
41 import org.onap.nbi.apis.serviceorder.repositories.ServiceOrderRepository;
42 import org.onap.nbi.apis.serviceorder.utils.JsonEntityConverter;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
45 import org.springframework.beans.factory.annotation.Autowired;
46 import org.springframework.beans.factory.annotation.Value;
47 import org.springframework.http.HttpStatus;
48 import org.springframework.http.ResponseEntity;
49 import org.springframework.stereotype.Service;
50 import org.springframework.util.CollectionUtils;
53 public class SOTaskProcessor {
55 @Value("${nbi.callForVNF}")
56 private boolean enableCallForVNF;
58 @Value("${onap.lcpCloudRegionId}")
59 private String lcpCloudRegionId;
61 @Value("${onap.tenantId}")
62 private String tenantId;
65 private ServiceOrderRepository serviceOrderRepository;
68 private ExecutionTaskRepository executionTaskRepository;
71 private SoClient soClient;
74 private static final Logger LOGGER = LoggerFactory.getLogger(SOTaskProcessor.class);
77 * Run the ServiceOrchestrator processing for a serviceOrderItem which with any sub relations
79 * @throws InterruptedException
81 public void processOrderItem(ExecutionTask executionTask) throws InterruptedException {
84 ServiceOrderInfoJson serviceOrderInfoJson = executionTask.getServiceOrderInfoJson();
85 ServiceOrder serviceOrder = serviceOrderRepository.findOne(serviceOrderInfoJson.getServiceOrderId());
86 ServiceOrderItem serviceOrderItem = null;
87 for (ServiceOrderItem item : serviceOrder.getOrderItem()) {
88 if (item.getId().equals(executionTask.getOrderItemId())) {
89 serviceOrderItem = item;
93 ServiceOrderInfo serviceOrderInfo = null;
96 JsonEntityConverter.convertJsonToServiceOrderInfo(serviceOrderInfoJson.getServiceOrderInfoJson());
97 } catch (IOException e) {
98 LOGGER.warn("Unable to read ServiceOrderInfo Json for serviceOrderId " + serviceOrder.getId(), e);
101 if (serviceOrderItem != null && StateType.ACKNOWLEDGED == serviceOrderItem.getState()) {
103 ResponseEntity<CreateServiceInstanceResponse> response = null;
105 response = postSORequest(serviceOrderItem, serviceOrderInfo);
106 } catch (NullPointerException e) {
107 LOGGER.warn("Enable to create service instance for serviceOrderItem.id=" + serviceOrderItem.getId(), e);
111 if (response == null) {
112 LOGGER.warn("response=null for serviceOrderItem.id=" + serviceOrderItem.getId());
113 serviceOrderItem.setState(StateType.FAILED);
115 updateServiceOrderItem(response.getBody(), serviceOrderItem);
117 if (response.getStatusCode() != HttpStatus.CREATED || response.getBody() == null
118 || response.getBody().getRequestReference() == null) {
119 serviceOrderItem.setState(StateType.FAILED);
121 serviceOrderItem.setState(StateType.INPROGRESS);
126 if (executionTask.getNbRetries() > 0) {
127 // TODO lancer en asynchrone
128 pollSoRequestStatus(serviceOrderItem);
129 if (serviceOrderItem.getState().equals(StateType.COMPLETED)) {
130 updateSuccessTask(executionTask);
132 int nbRetries = executionTask.getNbRetries();
133 executionTask.setNbRetries(--nbRetries);
134 executionTask.setLastAttemptDate(new Date());
135 executionTaskRepository.save(executionTask);
138 updateFailedTask(executionTask, serviceOrder);
142 updateServiceOrder(serviceOrder);
145 private ResponseEntity<CreateServiceInstanceResponse> postSORequest(ServiceOrderItem serviceOrderItem,
146 ServiceOrderInfo serviceOrderInfo) {
147 RequestDetails requestDetails = buildSoRequest(serviceOrderItem,
148 serviceOrderInfo.getServiceOrderItemInfos().get(serviceOrderItem.getId()).getCatalogResponse(),
149 serviceOrderInfo.getSubscriberInfo());
150 ResponseEntity<CreateServiceInstanceResponse> response = null;
152 switch (serviceOrderItem.getAction()) {
154 response = soClient.callCreateServiceInstance(requestDetails);
157 response = soClient.callDeleteServiceInstance(requestDetails, serviceOrderItem.getService().getId());
165 private void updateServiceOrder(ServiceOrder serviceOrder) {
166 boolean atLeastOneCompleted = false;
167 boolean atLeastOneNotFinished = false;
168 boolean atLeastOneFailed = false;
171 for (ServiceOrderItem serviceOrderItem : serviceOrder.getOrderItem()) {
172 switch (serviceOrderItem.getState()) {
174 atLeastOneCompleted = true;
178 atLeastOneNotFinished = true;
181 atLeastOneFailed = true;
189 if (atLeastOneNotFinished) {
190 serviceOrder.setState(StateType.INPROGRESS);
192 serviceOrder.setCompletionDateTime(new Date());
193 if (atLeastOneFailed) {
194 if (!atLeastOneCompleted) {
195 serviceOrder.setState(StateType.FAILED);
197 serviceOrder.setState(StateType.PARTIAL);
200 serviceOrder.setState(StateType.COMPLETED);
203 serviceOrderRepository.save(serviceOrder);
210 * @throws InterruptedException
212 private void pollSoRequestStatus(ServiceOrderItem orderItem) throws InterruptedException {
213 boolean stopPolling = false;
214 String requestId = orderItem.getRequestId();
215 GetRequestStatusResponse response = null;
218 while (!stopPolling) {
219 response = soClient.callGetRequestStatus(requestId);
220 if (response != null) {
221 if (response.getRequest().getRequestStatus().getPercentProgress() != 100) {
223 orderItem.setState(StateType.INPROGRESS);
225 } else if (RequestState.COMPLETE != response.getRequest().getRequestStatus().getRequestState()) {
226 orderItem.setState(StateType.FAILED);
229 orderItem.setState(StateType.COMPLETED);
233 orderItem.setState(StateType.INPROGRESS);
236 if (nbRetries == 3) {
243 * Build SO CREATE request from the ServiceOrder and catalog informations from SDC
247 * @param subscriberInfo
250 private RequestDetails buildSoRequest(ServiceOrderItem orderItem, LinkedHashMap<String, Object> sdcInfos,
251 SubscriberInfo subscriberInfo) {
252 RequestDetails requestDetails = new RequestDetails();
254 requestDetails.setSubscriberInfo(subscriberInfo);
256 ModelInfo modelInfo = new ModelInfo();
257 modelInfo.setModelType("service");
258 modelInfo.setModelInvariantId((String) sdcInfos.get("invariantUUID"));
259 modelInfo.setModelNameVersionId(orderItem.getService().getServiceSpecification().getId());
260 modelInfo.setModelName((String) sdcInfos.get("name"));
261 modelInfo.setModelVersion((String) sdcInfos.get("version"));
262 requestDetails.setModelInfo(modelInfo);
264 RequestInfo requestInfo = new RequestInfo();
265 requestInfo.setInstanceName(orderItem.getService().getName());
266 requestInfo.setSource("VID");
267 requestInfo.setSuppressRollback(false);
268 requestDetails.setRequestInfo(requestInfo);
270 RequestParameters requestParameters = new RequestParameters();
271 requestParameters.setSubscriptionServiceType((String) sdcInfos.get("name"));
272 requestParameters.setUserParams(
273 retrieveUserParamsFromServiceCharacteristics(orderItem.getService().getServiceCharacteristic()));
274 requestParameters.setaLaCarte(true);
275 requestDetails.setRequestParameters(requestParameters);
277 CloudConfiguration cloudConfiguration = new CloudConfiguration(lcpCloudRegionId, tenantId);
278 requestDetails.setCloudConfiguration(cloudConfiguration);
279 return requestDetails;
283 * Build a list of UserParams for the SO request by browsing a list of ServiceCharacteristics from
286 * @param characteristics
289 private List<UserParams> retrieveUserParamsFromServiceCharacteristics(List<ServiceCharacteristic> characteristics) {
290 List<UserParams> userParams = new ArrayList<UserParams>();
292 if (!CollectionUtils.isEmpty(characteristics)) {
293 for (ServiceCharacteristic characteristic : characteristics) {
294 UserParams userParam = new UserParams(characteristic.getName(),
295 characteristic.getValue().getServiceCharacteristicValue());
296 userParams.add(userParam);
305 * Update ServiceOrderItem with SO response by using serviceOrderRepository with the serviceOrderId
307 * @param createServiceInstanceResponse
310 private void updateServiceOrderItem(CreateServiceInstanceResponse createServiceInstanceResponse,
311 ServiceOrderItem orderItem) {
313 if (createServiceInstanceResponse != null && !orderItem.getState().equals(StateType.FAILED)) {
314 orderItem.getService().setId(createServiceInstanceResponse.getRequestReference().getInstanceId());
315 orderItem.setRequestId(createServiceInstanceResponse.getRequestReference().getRequestId());
320 * Update an executionTask in database when it's process with a success
322 * @param executionTask
324 private void updateSuccessTask(ExecutionTask executionTask) {
325 executionTaskRepository.delete(executionTask.getInternalId());
326 executionTaskRepository.updateReliedTaskAfterDelete(executionTask.getInternalId());
330 * @param executionTask
331 * @param serviceOrder
333 private void updateFailedTask(ExecutionTask executionTask, ServiceOrder serviceOrder) {
334 List<ExecutionTask> executionTasksToDelete = findExecutionTasksRecursively(executionTask);
335 for (ExecutionTask taskId : executionTasksToDelete) {
336 executionTaskRepository.delete(taskId);
339 for (ServiceOrderItem item : serviceOrder.getOrderItem()) {
340 for (ExecutionTask taskToDelete : executionTasksToDelete) {
341 if (taskToDelete.getOrderItemId().equals(item.getId())) {
342 item.setState(StateType.FAILED);
349 * @param executionTask
352 private List<ExecutionTask> findExecutionTasksRecursively(ExecutionTask executionTask) {
354 List<ExecutionTask> executionTasks = new ArrayList<>();
356 List<ExecutionTask> tasksReliedToAnOrderItemId =
357 executionTaskRepository.findTasksReliedToAnOrderItemId(executionTask.getInternalId());
359 if (CollectionUtils.isEmpty(tasksReliedToAnOrderItemId)) {
360 return Arrays.asList(executionTask);
362 for (ExecutionTask task : tasksReliedToAnOrderItemId) {
363 executionTasks.addAll(findExecutionTasksRecursively(task));
366 executionTasks.add(executionTask);
367 return executionTasks;