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 org.onap.nbi.apis.serviceorder.SoClient;
16 import org.onap.nbi.apis.serviceorder.model.ServiceCharacteristic;
17 import org.onap.nbi.apis.serviceorder.model.ServiceOrder;
18 import org.onap.nbi.apis.serviceorder.model.ServiceOrderItem;
19 import org.onap.nbi.apis.serviceorder.model.StateType;
20 import org.onap.nbi.apis.serviceorder.model.consumer.*;
21 import org.onap.nbi.apis.serviceorder.model.orchestrator.ExecutionTask;
22 import org.onap.nbi.apis.serviceorder.model.orchestrator.ServiceOrderInfo;
23 import org.onap.nbi.apis.serviceorder.repositories.ExecutionTaskRepository;
24 import org.onap.nbi.apis.serviceorder.repositories.ServiceOrderRepository;
25 import org.onap.nbi.apis.serviceorder.utils.JsonEntityConverter;
26 import org.onap.nbi.exceptions.TechnicalException;
27 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory;
29 import org.springframework.beans.factory.annotation.Autowired;
30 import org.springframework.beans.factory.annotation.Value;
31 import org.springframework.http.HttpStatus;
32 import org.springframework.http.ResponseEntity;
33 import org.springframework.stereotype.Service;
34 import org.springframework.util.CollectionUtils;
36 import java.io.IOException;
40 public class SOTaskProcessor {
42 @Value("${nbi.callForVNF}")
43 private boolean enableCallForVNF;
45 @Value("${onap.lcpCloudRegionId}")
46 private String lcpCloudRegionId;
48 @Value("${onap.tenantId}")
49 private String tenantId;
52 private ServiceOrderRepository serviceOrderRepository;
55 private ExecutionTaskRepository executionTaskRepository;
58 private SoClient soClient;
61 private static final Logger LOGGER = LoggerFactory.getLogger(SOTaskProcessor.class);
64 * Run the ServiceOrchestrator processing for a serviceOrderItem which with any sub relations
66 * @throws InterruptedException
68 public void processOrderItem(ExecutionTask executionTask) throws InterruptedException {
70 ServiceOrderInfo serviceOrderInfo = getServiceOrderInfo(executionTask);
72 ServiceOrder serviceOrder = serviceOrderRepository.findOne(serviceOrderInfo.getServiceOrderId());
73 ServiceOrderItem serviceOrderItem = getServiceOrderItem(executionTask, serviceOrder);
75 if (StateType.ACKNOWLEDGED == serviceOrderItem.getState()) {
77 ResponseEntity<CreateServiceInstanceResponse> response = postServiceOrderItem(serviceOrderInfo,
79 updateServiceOrderItem(response, serviceOrderItem,serviceOrder);
82 if (executionTask.getNbRetries() > 0 && StateType.FAILED != serviceOrderItem.getState()
84 // TODO lancer en asynchrone
85 pollSoRequestStatus(serviceOrderItem);
86 if (serviceOrderItem.getState().equals(StateType.COMPLETED)) {
87 updateSuccessTask(executionTask);
89 int nbRetries = executionTask.getNbRetries();
90 executionTask.setNbRetries(--nbRetries);
91 executionTask.setLastAttemptDate(new Date());
92 executionTaskRepository.save(executionTask);
95 updateFailedTask(executionTask, serviceOrder);
98 updateServiceOrder(serviceOrder);
101 private ResponseEntity<CreateServiceInstanceResponse> postServiceOrderItem(ServiceOrderInfo serviceOrderInfo,
102 ServiceOrderItem serviceOrderItem) {
103 ResponseEntity<CreateServiceInstanceResponse> response = null;
105 response = postSORequest(serviceOrderItem, serviceOrderInfo);
106 } catch (NullPointerException e) {
107 LOGGER.error("Unable to create service instance for serviceOrderItem.id=" + serviceOrderItem.getId(), e);
113 private ServiceOrderItem getServiceOrderItem(ExecutionTask executionTask, ServiceOrder serviceOrder) {
114 for (ServiceOrderItem item : serviceOrder.getOrderItem()) {
115 if (item.getId().equals(executionTask.getOrderItemId())) {
119 throw new TechnicalException(
120 "Unable to retrieve serviceOrderItem forexecutionTaskId " + executionTask.getInternalId());
123 private ServiceOrderInfo getServiceOrderInfo(ExecutionTask executionTask) {
124 String serviceOrderInfoJson = executionTask.getServiceOrderInfoJson();
125 ServiceOrderInfo serviceOrderInfo = null;
128 JsonEntityConverter.convertJsonToServiceOrderInfo(serviceOrderInfoJson);
129 } catch (IOException e) {
131 .error("Unable to read ServiceOrderInfo Json for executionTaskId " + executionTask.getInternalId(), e);
132 throw new TechnicalException(
133 "Unable to read ServiceOrderInfo Json for executionTaskId " + executionTask.getInternalId());
135 return serviceOrderInfo;
138 private ResponseEntity<CreateServiceInstanceResponse> postSORequest(ServiceOrderItem serviceOrderItem,
139 ServiceOrderInfo serviceOrderInfo) {
140 RequestDetails requestDetails = buildSoRequest(serviceOrderItem,
141 serviceOrderInfo.getServiceOrderItemInfos().get(serviceOrderItem.getId()).getCatalogResponse(),
142 serviceOrderInfo.getSubscriberInfo());
143 MSOPayload msoPayload = new MSOPayload(requestDetails);
144 ResponseEntity<CreateServiceInstanceResponse> response = null;
146 switch (serviceOrderItem.getAction()) {
148 response = soClient.callCreateServiceInstance(msoPayload);
151 response = soClient.callDeleteServiceInstance(msoPayload, serviceOrderItem.getService().getId());
159 private void updateServiceOrder(ServiceOrder serviceOrder) {
160 boolean atLeastOneCompleted = false;
161 boolean atLeastOneNotFinished = false;
162 boolean atLeastOneFailed = false;
164 for (ServiceOrderItem serviceOrderItem : serviceOrder.getOrderItem()) {
165 switch (serviceOrderItem.getState()) {
167 atLeastOneCompleted = true;
171 atLeastOneNotFinished = true;
174 atLeastOneFailed = true;
182 if (atLeastOneNotFinished) {
183 serviceOrder.setState(StateType.INPROGRESS);
185 serviceOrder.setCompletionDateTime(new Date());
186 if (atLeastOneFailed) {
187 if (!atLeastOneCompleted) {
188 serviceOrder.setState(StateType.FAILED);
190 serviceOrder.setState(StateType.PARTIAL);
193 serviceOrder.setState(StateType.COMPLETED);
196 serviceOrderRepository.save(serviceOrder);
203 private void pollSoRequestStatus(ServiceOrderItem orderItem) throws InterruptedException {
204 boolean stopPolling = false;
205 String requestId = orderItem.getRequestId();
206 GetRequestStatusResponse response = null;
209 while (!stopPolling) {
210 response = soClient.callGetRequestStatus(requestId);
211 if (response != null) {
212 if (response.getRequest().getRequestStatus().getPercentProgress() != 100) {
214 orderItem.setState(StateType.INPROGRESS);
216 } else if (RequestState.COMPLETE != response.getRequest().getRequestStatus().getRequestState()) {
217 orderItem.setState(StateType.FAILED);
220 orderItem.setState(StateType.COMPLETED);
224 orderItem.setState(StateType.INPROGRESS);
227 if (nbRetries == 3) {
234 * Build SO CREATE request from the ServiceOrder and catalog informations from SDC
238 * @param subscriberInfo
241 private RequestDetails buildSoRequest(ServiceOrderItem orderItem, Map<String, Object> sdcInfos,
242 SubscriberInfo subscriberInfo) {
243 RequestDetails requestDetails = new RequestDetails();
245 requestDetails.setSubscriberInfo(subscriberInfo);
247 ModelInfo modelInfo = new ModelInfo();
248 modelInfo.setModelType("service");
249 modelInfo.setModelInvariantId((String) sdcInfos.get("invariantUUID"));
250 modelInfo.setModelNameVersionId(orderItem.getService().getServiceSpecification().getId());
251 modelInfo.setModelVersionId(orderItem.getService().getServiceSpecification().getId());
252 modelInfo.setModelName((String) sdcInfos.get("name"));
253 modelInfo.setModelVersion((String) sdcInfos.get("version"));
254 requestDetails.setModelInfo(modelInfo);
256 RequestInfo requestInfo = new RequestInfo();
257 requestInfo.setInstanceName(orderItem.getService().getName());
258 requestInfo.setSource("VID");
259 requestInfo.setSuppressRollback(false);
260 requestInfo.setRequestorId("NBI");
261 requestDetails.setRequestInfo(requestInfo);
263 RequestParameters requestParameters = new RequestParameters();
264 requestParameters.setSubscriptionServiceType((String) sdcInfos.get("name"));
265 requestParameters.setUserParams(
266 retrieveUserParamsFromServiceCharacteristics(orderItem.getService().getServiceCharacteristic()));
267 requestParameters.setaLaCarte(true);
268 requestDetails.setRequestParameters(requestParameters);
270 CloudConfiguration cloudConfiguration = new CloudConfiguration(lcpCloudRegionId, tenantId);
271 requestDetails.setCloudConfiguration(cloudConfiguration);
272 return requestDetails;
276 * Build a list of UserParams for the SO request by browsing a list of ServiceCharacteristics from SDC
278 private List<UserParams> retrieveUserParamsFromServiceCharacteristics(List<ServiceCharacteristic> characteristics) {
279 List<UserParams> userParams = new ArrayList<UserParams>();
281 if (!CollectionUtils.isEmpty(characteristics)) {
282 for (ServiceCharacteristic characteristic : characteristics) {
283 UserParams userParam = new UserParams(characteristic.getName(),
284 characteristic.getValue().getServiceCharacteristicValue());
285 userParams.add(userParam);
294 * Update ServiceOrderItem with SO response by using serviceOrderRepository with the serviceOrderId
297 * @param serviceOrder
299 private void updateServiceOrderItem(ResponseEntity<CreateServiceInstanceResponse> response,
300 ServiceOrderItem orderItem, ServiceOrder serviceOrder) {
302 if (response == null) {
303 LOGGER.warn("response=null for serviceOrderItem.id=" + orderItem.getId());
304 orderItem.setState(StateType.FAILED);
307 CreateServiceInstanceResponse createServiceInstanceResponse = response.getBody();
308 if (createServiceInstanceResponse != null && !orderItem.getState().equals(StateType.FAILED)) {
309 orderItem.getService().setId(createServiceInstanceResponse.getRequestReferences().getInstanceId());
310 orderItem.setRequestId(createServiceInstanceResponse.getRequestReferences().getRequestId());
313 if (response.getStatusCode() != HttpStatus.CREATED || response.getBody() == null
314 || response.getBody().getRequestReferences() == null) {
315 orderItem.setState(StateType.FAILED);
317 orderItem.setState(StateType.INPROGRESS);
320 serviceOrderRepository.save(serviceOrder);
324 * Update an executionTask in database when it's process with a success
326 * @param executionTask
328 private void updateSuccessTask(ExecutionTask executionTask) {
329 executionTaskRepository.delete(executionTask.getInternalId());
330 executionTaskRepository.updateReliedTaskAfterDelete(executionTask.getInternalId());
335 * @param executionTask
336 * @param serviceOrder
338 private void updateFailedTask(ExecutionTask executionTask, ServiceOrder serviceOrder) {
339 List<ExecutionTask> executionTasksToDelete = findExecutionTasksRecursively(executionTask);
340 for (ExecutionTask taskId : executionTasksToDelete) {
341 executionTaskRepository.delete(taskId);
343 for (ServiceOrderItem item : serviceOrder.getOrderItem()) {
344 for (ExecutionTask taskToDelete : executionTasksToDelete) {
345 if (taskToDelete.getOrderItemId().equals(item.getId())) {
346 item.setState(StateType.FAILED);
353 * @param executionTask
356 private List<ExecutionTask> findExecutionTasksRecursively(ExecutionTask executionTask) {
358 List<ExecutionTask> executionTasks = new ArrayList<>();
360 List<ExecutionTask> tasksReliedToAnOrderItemId =
361 executionTaskRepository.findTasksReliedToAnOrderItemId(executionTask.getInternalId());
363 if (CollectionUtils.isEmpty(tasksReliedToAnOrderItemId)) {
364 return Arrays.asList(executionTask);
366 for (ExecutionTask task : tasksReliedToAnOrderItemId) {
367 executionTasks.addAll(findExecutionTasksRecursively(task));
370 executionTasks.add(executionTask);
371 return executionTasks;