2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package org.onap.vid.services;
23 import static com.google.common.collect.Streams.concat;
24 import static java.util.function.Function.identity;
25 import static java.util.stream.Collectors.counting;
26 import static java.util.stream.Collectors.groupingBy;
27 import static java.util.stream.Stream.empty;
28 import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;
29 import static org.apache.commons.lang3.StringUtils.isNotEmpty;
30 import static org.onap.vid.controller.MsoController.SVC_INSTANCE_ID;
31 import static org.onap.vid.controller.MsoController.VNF_INSTANCE_ID;
32 import static org.onap.vid.utils.KotlinUtilsKt.JACKSON_OBJECT_MAPPER;
34 import com.google.common.collect.ImmutableMap;
35 import java.io.IOException;
36 import java.time.ZonedDateTime;
37 import java.util.ArrayList;
38 import java.util.Calendar;
39 import java.util.Date;
40 import java.util.List;
42 import java.util.Objects;
43 import java.util.UUID;
44 import java.util.function.Consumer;
45 import java.util.stream.Stream;
46 import org.hibernate.SessionFactory;
47 import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
48 import org.onap.vid.aai.AaiClientInterface;
49 import org.onap.vid.aai.model.ResourceType;
50 import org.onap.vid.dal.AsyncInstantiationRepository;
51 import org.onap.vid.exceptions.DbFailureUncheckedException;
52 import org.onap.vid.exceptions.GenericUncheckedException;
53 import org.onap.vid.exceptions.MaxRetriesException;
54 import org.onap.vid.exceptions.OperationNotAllowedException;
55 import org.onap.vid.job.Job;
56 import org.onap.vid.job.Job.JobStatus;
57 import org.onap.vid.job.JobAdapter;
58 import org.onap.vid.job.JobType;
59 import org.onap.vid.job.JobsBrokerService;
60 import org.onap.vid.job.impl.JobSharedData;
61 import org.onap.vid.model.Action;
62 import org.onap.vid.model.NameCounter;
63 import org.onap.vid.model.ResourceInfo;
64 import org.onap.vid.model.ServiceInfo;
65 import org.onap.vid.model.serviceInstantiation.BaseResource;
66 import org.onap.vid.model.serviceInstantiation.ServiceInstantiation;
67 import org.onap.vid.model.serviceInstantiation.VfModule;
68 import org.onap.vid.mso.MsoBusinessLogicImpl;
69 import org.onap.vid.mso.MsoProperties;
70 import org.onap.vid.mso.MsoUtil;
71 import org.onap.vid.mso.RestObject;
72 import org.onap.vid.mso.model.ModelInfo;
73 import org.onap.vid.mso.rest.AsyncRequestStatus;
74 import org.onap.vid.mso.rest.RequestStatus;
75 import org.onap.vid.properties.Features;
76 import org.onap.vid.utils.DaoUtils;
77 import org.onap.vid.utils.TimeUtils;
78 import org.springframework.beans.factory.annotation.Autowired;
79 import org.springframework.stereotype.Service;
80 import org.togglz.core.manager.FeatureManager;
83 public class AsyncInstantiationBusinessLogicImpl implements
84 AsyncInstantiationBusinessLogic {
86 private static final int MAX_RETRIES_GETTING_COUNTER = 100;
87 private static final int MAX_RETRIES_GETTING_FREE_NAME_FROM_AAI = 10000;
88 public static final String NAME_FOR_CHECK_AAI_STATUS = "NAME_FOR_CHECK_AAI_STATUS";
90 private final JobAdapter jobAdapter;
92 private final JobsBrokerService jobService;
94 private final CloudOwnerService cloudOwnerService;
96 private final AsyncInstantiationRepository asyncInstantiationRepository;
98 private SessionFactory sessionFactory;
100 private AaiClientInterface aaiClient;
102 private FeatureManager featureManager;
104 private AuditService auditService;
107 private int maxRetriesGettingFreeNameFromAai = MAX_RETRIES_GETTING_FREE_NAME_FROM_AAI;
109 private static final EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(AsyncInstantiationBusinessLogicImpl.class);
110 private Map<String, JobStatus> msoStateToJobStatusMap = ImmutableMap.<String, JobStatus>builder()
111 .put("inprogress", JobStatus.IN_PROGRESS)
112 .put("failed", JobStatus.FAILED)
113 .put("pause", JobStatus.PAUSE)
114 .put("paused", JobStatus.PAUSE)
115 .put("complete", JobStatus.COMPLETED)
116 .put("pending", JobStatus.IN_PROGRESS)
117 .put("pendingmanualtask", JobStatus.PAUSE)
118 .put("unlocked", JobStatus.IN_PROGRESS)
119 .put("aborted", JobStatus.COMPLETED_WITH_ERRORS)
120 .put("rolledback", JobStatus.FAILED)
121 .put("rolledbacktoassigned", JobStatus.FAILED)
122 .put("rolledbacktocreated", JobStatus.FAILED)
127 public AsyncInstantiationBusinessLogicImpl(JobAdapter jobAdapter,
128 JobsBrokerService jobService,
129 SessionFactory sessionFactory,
130 AaiClientInterface aaiClient,
131 FeatureManager featureManager,
132 CloudOwnerService cloudOwnerService, AsyncInstantiationRepository asyncInstantiationRepository,
133 AuditService auditService) {
134 this.jobAdapter = jobAdapter;
135 this.jobService = jobService;
136 this.sessionFactory = sessionFactory;
137 this.aaiClient = aaiClient;
138 this.featureManager = featureManager;
139 this.cloudOwnerService = cloudOwnerService;
140 this.asyncInstantiationRepository = asyncInstantiationRepository;
141 this.auditService = auditService;
145 public List<ServiceInfo> getAllServicesInfo() {
146 return asyncInstantiationRepository.getAllServicesInfo();
149 JobType getJobType(ServiceInstantiation request) {
150 if (request.isALaCarte()) {
151 switch (defaultIfNull(request.getAction(), Action.Create)) {
153 return JobType.ALaCarteService;
155 return JobType.ALaCarteService;
157 return JobType.ALaCarteServiceInstantiation;
160 return JobType.MacroServiceInstantiation;
165 public List<UUID> pushBulkJob(ServiceInstantiation request, String userId) {
167 List<UUID> uuids = new ArrayList<>();
168 Date createdBulkDate = Calendar.getInstance().getTime();
169 int bulkSize = request.getBulkSize();
170 UUID templateId = UUID.randomUUID();
171 for (int i = 0; i < bulkSize; i++) {
172 ServiceInstantiation requestPerJob = prepareServiceToBeUnique(request);
173 ServiceInfo.ServiceAction serviceAction = getAction(requestPerJob);
174 JobType jobType = getJobType(requestPerJob);
175 final String optimisticUniqueServiceInstanceName = bulkSize>1 ? //only bulk with more than 1 service need to get multiple names
176 getOptimisticUniqueServiceInstanceName(requestPerJob.getInstanceName()) : requestPerJob.getInstanceName();
177 Job job = jobAdapter.createServiceInstantiationJob(jobType, requestPerJob, templateId, userId, request.getTestApi(), optimisticUniqueServiceInstanceName, i);
178 UUID jobId = job.getUuid();
180 asyncInstantiationRepository.saveServiceInfo(createServiceInfo(userId, requestPerJob, jobId, templateId, createdBulkDate, optimisticUniqueServiceInstanceName, serviceAction));
181 asyncInstantiationRepository.addJobRequest(jobId, requestPerJob);
182 auditService.auditVidStatus(jobId, job.getStatus());
190 public Map<String, Long> getSummarizedChildrenMap(ServiceInstantiation serviceInstantiation){
191 Stream<String> existingTypesStream =
192 allDeepChildResources(serviceInstantiation)
193 .map(this::getModelTypes)
194 .flatMap(identity());
196 Map<String, Long> existingTypesCounters =
197 existingTypesStream.collect(groupingBy(identity(), counting()));
199 return existingTypesCounters;
202 private Stream<String> getModelTypes(BaseResource resource) {
205 .map(BaseResource::getModelInfo)
206 .filter(Objects::nonNull)
207 .map(ModelInfo::getModelType),
208 streamVolumeGroups(resource)
212 private Stream<String> streamVolumeGroups(BaseResource resource) {
213 return hasVolumeGroup(resource)
214 ? Stream.of("volumeGroup")
218 private boolean hasVolumeGroup(BaseResource resource) {
220 resource instanceof VfModule
221 && isNotEmpty(((VfModule) resource).getVolumeGroupInstanceName());
224 private Stream<BaseResource> allDeepChildResources(BaseResource resource) {
228 .map(it -> concat(Stream.of(it), allDeepChildResources(it)))
229 .flatMap(identity());
232 private ServiceInfo.ServiceAction getAction(ServiceInstantiation request) {
233 if (request.getAction() == null) {
234 //throw new GenericUncheckedException("Required 'action' field not provided at service level");
235 return Action.Create.getServiceAction();
237 return request.getAction().getServiceAction();
241 private String getOptimisticUniqueServiceInstanceName(String instanceName) {
242 return isNotEmpty(instanceName) ? getUniqueNameFromDbOnly(instanceName) : instanceName;
245 protected ServiceInfo createServiceInfo(String userId, ServiceInstantiation serviceInstantiation, UUID jobId, UUID templateId, Date createdBulkDate, String optimisticUniqueServiceInstanceName, ServiceInfo.ServiceAction serviceAction) {
246 return new ServiceInfo(
248 serviceInstantiation.isALaCarte(),
249 Job.JobStatus.PENDING, serviceInstantiation.isPause(), jobId, templateId,
250 serviceInstantiation.getOwningEntityId(),
251 serviceInstantiation.getOwningEntityName(),
252 serviceInstantiation.getProjectName(),
253 serviceInstantiation.getAicZoneId(),
254 serviceInstantiation.getAicZoneName(),
255 serviceInstantiation.getTenantId(),
256 serviceInstantiation.getTenantName(),
257 serviceInstantiation.getLcpCloudRegionId(),
259 serviceInstantiation.getSubscriptionServiceType(),
260 serviceInstantiation.getSubscriberName(),
261 serviceInstantiation.getGlobalSubscriberId(),
262 serviceInstantiation.getInstanceId(),
263 optimisticUniqueServiceInstanceName,
264 serviceInstantiation.getModelInfo().getModelVersionId(),
265 serviceInstantiation.getModelInfo().getModelName(),
266 serviceInstantiation.getModelInfo().getModelVersion(),
273 public boolean isPartOfBulk(UUID jobId) {
277 ServiceInfo serviceInfo = asyncInstantiationRepository.getServiceInfoByJobId(jobId);
278 UUID templateId = serviceInfo.getTemplateId();
279 if (templateId != null) {
280 return getNumberOfJobsInBulk(templateId) > 1;
286 private int getNumberOfJobsInBulk(UUID templateId) {
287 String hqlSelectJob = "from JobDaoImpl where templateId = :templateId";
288 return DaoUtils.tryWithSessionAndTransaction(sessionFactory, session ->
289 session.createQuery(hqlSelectJob)
290 .setText("templateId", templateId.toString())
297 public String getServiceInstantiationPath(ServiceInstantiation serviceInstantiationRequest) {
298 //in case pause flag is true - use assign , else - use create.
299 return MsoBusinessLogicImpl.validateEndpointPath(
300 serviceInstantiationRequest.isPause() ?
301 MsoProperties.MSO_REST_API_SERVICE_INSTANCE_ASSIGN : MsoProperties.MSO_RESTAPI_SERVICE_INSTANCE
306 public String getServiceDeletionPath(String serviceInstanceId) {
307 return MsoBusinessLogicImpl.validateEndpointPath( MsoProperties.MSO_RESTAPI_SERVICE_INSTANCE) + "/" + serviceInstanceId;
311 public String getVnfInstantiationPath(String serviceInstanceId) {
312 return MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_VNF_INSTANCE).
313 replaceFirst(SVC_INSTANCE_ID, serviceInstanceId);
317 public String getVnfDeletionPath(String serviceInstanceId, String vnfInstanceId) {
318 return (MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_VNF_INSTANCE)
319 + '/' + vnfInstanceId)
320 .replaceFirst(SVC_INSTANCE_ID, serviceInstanceId).replaceFirst(VNF_INSTANCE_ID, vnfInstanceId);
324 public String getNetworkInstantiationPath(String serviceInstanceId) {
325 return MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_NETWORK_INSTANCE).
326 replaceFirst(SVC_INSTANCE_ID, serviceInstanceId);
330 public String getVfmoduleInstantiationPath(String serviceInstanceId, String vnfInstanceId) {
331 return MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_VF_MODULE_INSTANCE)
332 .replaceFirst(SVC_INSTANCE_ID, serviceInstanceId)
333 .replaceFirst(VNF_INSTANCE_ID, vnfInstanceId);
337 public String getVfModuleReplacePath(String serviceInstanceId, String vnfInstanceId, String vfModuleInstanceId)
339 return MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_VF_MODULE_INSTANCE)
340 .replaceFirst(SVC_INSTANCE_ID, serviceInstanceId)
341 .replaceFirst(VNF_INSTANCE_ID, vnfInstanceId)
342 + "/" + vfModuleInstanceId
347 public String getVfModuleDeletePath(String serviceInstanceId, String vnfInstanceId, String vfModuleInstanceId) {
348 return MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_VF_MODULE_INSTANCE)
349 .replaceFirst(SVC_INSTANCE_ID, serviceInstanceId)
350 .replaceFirst(VNF_INSTANCE_ID, vnfInstanceId)
351 + "/" + vfModuleInstanceId;
355 public String getVolumeGroupInstantiationPath(String serviceInstanceId, String vnfInstanceId) {
356 return MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_VOLUME_GROUP_INSTANCE)
357 .replaceFirst(SVC_INSTANCE_ID, serviceInstanceId)
358 .replaceFirst(VNF_INSTANCE_ID, vnfInstanceId);
362 public String getInstanceGroupInstantiationPath() {
363 return MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_INSTANCE_GROUP);
367 public String getInstanceGroupMemberInstantiationPath(String vnfGroupInstanceId) {
368 return MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_INSTANCE_GROUP)
369 + '/' + vnfGroupInstanceId + "/addMembers";
373 public String getInstanceGroupDeletePath(String instanceGroupId) {
374 return MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_INSTANCE_GROUP)
375 + '/' + instanceGroupId;
379 public String getInstanceGroupMemberDeletePath(String vnfGroupInstanceId){
380 return MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_INSTANCE_GROUP)
381 + '/' + vnfGroupInstanceId + "/removeMembers";
385 public String getNetworkDeletePath(String serviceInstanceId, String networkInstanceId) {
386 return (MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_NETWORK_INSTANCE)
387 + "/" + networkInstanceId)
388 .replaceFirst(SVC_INSTANCE_ID, serviceInstanceId);
392 public String getResumeRequestPath(String requestId) {
393 return MsoBusinessLogicImpl.validateEndpointPath("mso.restapi.resume.orc.req")
394 .replaceFirst("<request_id>", requestId);
398 public String getOrchestrationRequestsPath() {
399 return MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_GET_ORC_REQ);
403 public ServiceInfo updateServiceInfo(UUID jobUUID, Consumer<ServiceInfo> serviceUpdater) {
404 ServiceInfo serviceInfo = asyncInstantiationRepository.getServiceInfoByJobId(jobUUID);
405 serviceUpdater.accept(serviceInfo);
406 asyncInstantiationRepository.saveServiceInfo(serviceInfo);
411 public ServiceInfo updateServiceInfoAndAuditStatus(UUID jobUuid, JobStatus jobStatus) {
412 auditService.auditVidStatus(jobUuid, jobStatus);
413 return updateServiceInfo(jobUuid, x -> setServiceInfoStatus(x, jobStatus));
416 private boolean isRetryEnabledForStatus(JobStatus jobStatus) {
417 return featureManager.isActive(Features.FLAG_1902_RETRY_JOB) &&
418 (jobStatus==JobStatus.COMPLETED_WITH_ERRORS || jobStatus==JobStatus.FAILED);
421 private void setServiceInfoStatus(ServiceInfo serviceInfo, JobStatus jobStatus) {
422 serviceInfo.setJobStatus(jobStatus);
423 serviceInfo.setStatusModifiedDate(new Date());
424 serviceInfo.setRetryEnabled(isRetryEnabledForStatus(jobStatus));
427 public Job.JobStatus calcStatus(AsyncRequestStatus asyncRequestStatus) {
428 String msoRequestState = asyncRequestStatus.request.requestStatus.getRequestState().toLowerCase().replaceAll("[^a-z]+", "");
429 JobStatus jobStatus = msoStateToJobStatusMap.get(msoRequestState);
430 return (jobStatus != null ? jobStatus : JobStatus.IN_PROGRESS);
434 public void handleFailedInstantiation(UUID jobUUID) {
435 ServiceInfo serviceInfo = asyncInstantiationRepository.getServiceInfoByJobId(jobUUID);
436 List<ServiceInfo> serviceInfoList = asyncInstantiationRepository.getServiceInfoByTemplateIdAndJobStatus(serviceInfo.getTemplateId(), JobStatus.PENDING);
437 serviceInfoList.forEach(si -> updateServiceInfoAndAuditStatus(si.getJobId(), JobStatus.STOPPED));
441 public void deleteJob(UUID jobId) {
442 jobService.delete(jobId);
443 Date now = new Date();
444 updateServiceInfo(jobId, x -> x.setDeletedAt(now));
448 public void hideServiceInfo(UUID jobUUID) {
449 ServiceInfo serviceInfo = asyncInstantiationRepository.getServiceInfoByJobId(jobUUID);
450 if (!serviceInfo.getJobStatus().isFinal()) {
451 String message = String.format("jobId %s: Service status does not allow hide service, status = %s",
452 serviceInfo.getJobId(),
453 serviceInfo.getJobStatus());
454 logger.error(EELFLoggerDelegate.errorLogger, message);
455 throw new OperationNotAllowedException(message);
457 serviceInfo.setHidden(true);
458 asyncInstantiationRepository.saveServiceInfo(serviceInfo);
462 public int getCounterForName(String name) {
464 String hqlSelectNC = "from NameCounter where name = :name";
465 String hqlUpdateCounter = "update NameCounter set counter = :newCounter " +
466 "where name= :name " +
467 "and counter= :prevCounter";
469 Integer counter = null;
470 GenericUncheckedException lastException = null;
471 for (int i = 0; i< MAX_RETRIES_GETTING_COUNTER && counter==null; i++) {
473 counter = calcCounter(name, hqlSelectNC, hqlUpdateCounter);
475 catch (GenericUncheckedException exception) {
476 lastException = exception; //do nothing, we will try again in the loop
484 throw lastException!=null ? new DbFailureUncheckedException(lastException) :
485 new DbFailureUncheckedException("Failed to get counter for "+name+" due to unknown error");
489 private Integer calcCounter(String name, String hqlSelectNC, String hqlUpdateCounter) {
491 counter = DaoUtils.tryWithSessionAndTransaction(sessionFactory, session -> {
492 NameCounter nameCounter = (NameCounter) session.createQuery(hqlSelectNC)
493 .setText("name", name)
495 if (nameCounter != null) {
496 int updatedRows = session.createQuery(hqlUpdateCounter)
497 .setText("name", nameCounter.getName())
498 .setInteger("prevCounter", nameCounter.getCounter())
499 .setInteger("newCounter", nameCounter.getCounter() + 1)
501 if (updatedRows == 1) {
502 return nameCounter.getCounter() + 1;
505 Object nameAsId = session.save(new NameCounter(name));
507 if (nameAsId != null) {
511 //in case of failure return null, in order to continue the loop
518 public int getMaxRetriesGettingFreeNameFromAai() {
519 return maxRetriesGettingFreeNameFromAai;
523 public void setMaxRetriesGettingFreeNameFromAai(int maxRetriesGettingFreeNameFromAai) {
524 this.maxRetriesGettingFreeNameFromAai = maxRetriesGettingFreeNameFromAai;
528 public String getUniqueName(String name, ResourceType resourceType) {
529 //check that name aai response well before increasing counter from DB
530 //Prevents unnecessary increasing of the counter while AAI doesn't response
531 isNameFreeInAai(NAME_FOR_CHECK_AAI_STATUS, resourceType);
533 for (int i=0; i<getMaxRetriesGettingFreeNameFromAai(); i++) {
534 String newName = getUniqueNameFromDbOnly(name);
535 if (isNameFreeInAai(newName, resourceType)) {
540 throw new MaxRetriesException("can't find unused name for "+name, getMaxRetriesGettingFreeNameFromAai());
544 public ServiceInstantiation prepareServiceToBeUnique(ServiceInstantiation serviceInstantiation) {
546 ServiceInstantiation clonedServiceInstantiation = JACKSON_OBJECT_MAPPER.readValue(
547 JACKSON_OBJECT_MAPPER.writeValueAsBytes(serviceInstantiation), ServiceInstantiation.class);
548 clonedServiceInstantiation.setBulkSize(1);
549 return replaceAllTrackById(clonedServiceInstantiation);
550 } catch (IOException e) {
551 throw new GenericUncheckedException(e);
556 private<T extends BaseResource> T replaceAllTrackById(T resource) {
557 resource.setTrackById(UUID.randomUUID().toString());
558 resource.getChildren().forEach(this::replaceAllTrackById);
563 public List<UUID> retryJob(ServiceInstantiation request, UUID jobId, String userId ) {
564 updateServiceInfo(jobId, si->si.setRetryEnabled(false));
565 return pushBulkJob(request, userId);
569 public List<UUID> retryJob(UUID jobId, String userId) {
570 ServiceInstantiation serviceInstantiationRequest = asyncInstantiationRepository.getJobRequest(jobId);
571 enrichBulkForRetry(serviceInstantiationRequest, jobId);
574 logger.debug(EELFLoggerDelegate.debugLogger, "retry ServiceInstantiation request: "+
575 JACKSON_OBJECT_MAPPER.writeValueAsString(serviceInstantiationRequest));
576 } catch (Exception e) {
577 logger.error(EELFLoggerDelegate.errorLogger, "failed to log retry of ServiceInstantiation request ", e);
579 return retryJob(serviceInstantiationRequest, jobId, userId);
583 public ServiceInstantiation getBulkForRetry(UUID jobId) {
584 return enrichBulkForRetry( asyncInstantiationRepository.getJobRequest(jobId), jobId);
588 public void addResourceInfo(JobSharedData sharedData, Job.JobStatus jobStatus, String instanceId) {
589 String trackById = ((BaseResource) sharedData.getRequest()).getTrackById();
590 ResourceInfo resourceInfo = new ResourceInfo(trackById, sharedData.getRootJobId(), instanceId, jobStatus, null);
591 asyncInstantiationRepository.saveResourceInfo(resourceInfo);
595 public void addFailedResourceInfo(JobSharedData sharedData, RestObject msoResponse) {
596 String trackById = ((BaseResource) sharedData.getRequest()).getTrackById();
597 String errorMessage = MsoUtil.formatExceptionAdditionalInfo(msoResponse.getStatusCode(), msoResponse.getRaw());
598 AsyncRequestStatus asyncRequestStatus = convertMessageToAsyncRequestStatus(errorMessage);
599 ResourceInfo resourceInfo = new ResourceInfo(trackById, sharedData.getRootJobId(), null, JobStatus.FAILED, asyncRequestStatus);
601 asyncInstantiationRepository.saveResourceInfo(resourceInfo);
605 public void updateResourceInfo(JobSharedData sharedData, JobStatus jobStatus, AsyncRequestStatus message) {
606 ResourceInfo resourceInfo = asyncInstantiationRepository.getResourceInfoByTrackId(((BaseResource) sharedData.getRequest()).getTrackById());
607 resourceInfo.setJobStatus(jobStatus);
608 if (jobStatus.isFailure()) {
609 resourceInfo.setErrorMessage(message);
611 asyncInstantiationRepository.saveResourceInfo(resourceInfo);
614 public AsyncRequestStatus convertMessageToAsyncRequestStatus(String message) {
615 RequestStatus requestStatus = new RequestStatus("FAILED", message, TimeUtils.zonedDateTimeToString(ZonedDateTime.now()));
616 AsyncRequestStatus.Request request = new AsyncRequestStatus.Request(requestStatus);
617 return new AsyncRequestStatus(request);
620 protected String getUniqueNameFromDbOnly(String name) {
621 int counter = getCounterForName(name);
622 return formatNameAndCounter(name, counter);
625 //the method is protected so we can call it in the UT
626 protected String formatNameAndCounter(String name, int counter) {
627 return counter==0 ? name : name + "_" + String.format("%03d", counter);
630 private boolean isNameFreeInAai(String name, ResourceType resourceType){
631 return !aaiClient.isNodeTypeExistsByName(name, resourceType);
635 public ServiceInstantiation enrichBulkForRetry(ServiceInstantiation serviceInstantiation, UUID jobId){
636 Map<String, ResourceInfo> resourceInfoByTrackId = asyncInstantiationRepository.getResourceInfoByRootJobId(jobId);
638 return setResourceStatus(resourceInfoByTrackId, serviceInstantiation);
641 protected String readStatusMsg(ResourceInfo resourceInfo){
642 if(resourceInfo!=null && resourceInfo.getErrorMessage()!=null && resourceInfo.getErrorMessage().request != null &&resourceInfo.getErrorMessage().request.requestStatus != null ) {
643 return resourceInfo.getErrorMessage().request.requestStatus.getStatusMessage();
648 private<T extends BaseResource> T setResourceStatus(Map<String, ResourceInfo> resourceInfoByTrackId, T resource) {
649 ResourceInfo resourceInfo = resourceInfoByTrackId.get(resource.getTrackById());
650 if(resourceInfo != null) {
651 boolean failed = resourceInfo.getJobStatus().isFailure();
652 resource.setIsFailed(failed);
653 resource.setStatusMessage(readStatusMsg(resourceInfo));
655 // if(resource.getAction().equals(Action.Delete)){
656 // TODO not yet implemented- completed after delete should remove the node
657 resource.setAction(Action.None);
658 resource.setInstanceId(resourceInfo.getInstanceId());
661 resource.getChildren().forEach(child -> setResourceStatus(resourceInfoByTrackId, child));