Merge from ECOMP's repository
[vid.git] / vid-app-common / src / main / java / org / onap / vid / services / AsyncInstantiationBusinessLogicImpl.java
1 package org.onap.vid.services;
2
3 import com.fasterxml.jackson.core.type.TypeReference;
4 import com.fasterxml.jackson.databind.ObjectMapper;
5 import com.google.common.collect.ImmutableList;
6 import com.google.common.collect.ImmutableMap;
7 import org.apache.commons.lang3.StringUtils;
8 import org.hibernate.SessionFactory;
9 import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
10 import org.onap.portalsdk.core.service.DataAccessService;
11 import org.onap.vid.aai.AaiClientInterface;
12 import org.onap.vid.aai.ExceptionWithRequestInfo;
13 import org.onap.vid.aai.model.ResourceType;
14 import org.onap.vid.changeManagement.RequestDetailsWrapper;
15 import org.onap.vid.exceptions.DbFailureUncheckedException;
16 import org.onap.vid.exceptions.GenericUncheckedException;
17 import org.onap.vid.exceptions.MaxRetriesException;
18 import org.onap.vid.exceptions.OperationNotAllowedException;
19 import org.onap.vid.job.Job;
20 import org.onap.vid.job.Job.JobStatus;
21 import org.onap.vid.job.JobAdapter;
22 import org.onap.vid.job.JobType;
23 import org.onap.vid.job.JobsBrokerService;
24 import org.onap.vid.model.Action;
25 import org.onap.vid.model.JobAuditStatus;
26 import org.onap.vid.model.NameCounter;
27 import org.onap.vid.model.ServiceInfo;
28 import org.onap.vid.model.serviceInstantiation.*;
29 import org.onap.vid.mso.MsoBusinessLogicImpl;
30 import org.onap.vid.mso.MsoProperties;
31 import org.onap.vid.mso.model.*;
32 import org.onap.vid.mso.model.ServiceInstantiationRequestDetails.RequestParameters;
33 import org.onap.vid.mso.model.ServiceInstantiationRequestDetails.*;
34 import org.onap.vid.mso.model.VfModuleInstantiationRequestDetails.RequestParametersVfModule;
35 import org.onap.vid.mso.model.VfModuleInstantiationRequestDetails.UserParamMap;
36 import org.onap.vid.mso.rest.AsyncRequestStatus;
37 import org.onap.vid.mso.rest.SubscriberInfo;
38 import org.onap.vid.properties.Features;
39 import org.onap.vid.utils.DaoUtils;
40 import org.springframework.beans.factory.annotation.Autowired;
41 import org.springframework.stereotype.Service;
42 import org.togglz.core.manager.FeatureManager;
43
44 import java.sql.Timestamp;
45 import java.time.LocalDateTime;
46 import java.util.*;
47 import java.util.function.Consumer;
48 import java.util.stream.Collectors;
49
50 import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;
51 import static org.onap.vid.controller.MsoController.SVC_INSTANCE_ID;
52 import static org.onap.vid.controller.MsoController.VNF_INSTANCE_ID;
53 import static org.onap.vid.utils.Logging.debugRequestDetails;
54
55 @Service
56 public class AsyncInstantiationBusinessLogicImpl implements
57         AsyncInstantiationBusinessLogic {
58
59     private static final int MAX_RETRIES_GETTING_COUNTER = 100;
60     private static final int MAX_RETRIES_GETTING_FREE_NAME_FROM_AAI = 10000;
61     public static final String NAME_FOR_CHECK_AAI_STATUS = "NAME_FOR_CHECK_AAI_STATUS";
62     private static final String VID_SOURCE = "VID";
63
64     private final DataAccessService dataAccessService;
65
66     private final JobAdapter jobAdapter;
67
68     private final JobsBrokerService jobService;
69
70     private final CloudOwnerService cloudOwnerService;
71
72     private SessionFactory sessionFactory;
73
74     private AaiClientInterface aaiClient;
75
76     private FeatureManager featureManager;
77
78     private int maxRetriesGettingFreeNameFromAai = MAX_RETRIES_GETTING_FREE_NAME_FROM_AAI;
79
80     private static final EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(AsyncInstantiationBusinessLogicImpl.class);
81     private Map<String, JobStatus> msoStateToJobStatusMap = ImmutableMap.<String, JobStatus>builder()
82             .put("inprogress", JobStatus.IN_PROGRESS)
83             .put("failed", JobStatus.FAILED)
84             .put("pause", JobStatus.PAUSE)
85             .put("paused", JobStatus.PAUSE)
86             .put("complete", JobStatus.COMPLETED)
87             .put("pending", JobStatus.IN_PROGRESS)
88             .put("pendingmanualtask", JobStatus.PAUSE)
89             .put("unlocked", JobStatus.IN_PROGRESS)
90             .build();
91
92
93     @Autowired
94     public AsyncInstantiationBusinessLogicImpl(DataAccessService dataAccessService,
95                                                JobAdapter jobAdapter,
96                                                JobsBrokerService jobService,
97                                                SessionFactory sessionFactory,
98                                                AaiClientInterface aaiClient,
99                                                FeatureManager featureManager,
100                                                CloudOwnerService cloudOwnerService) {
101         this.dataAccessService = dataAccessService;
102         this.jobAdapter = jobAdapter;
103         this.jobService = jobService;
104         this.sessionFactory = sessionFactory;
105         this.aaiClient = aaiClient;
106         this.featureManager = featureManager;
107         this.cloudOwnerService = cloudOwnerService;
108     }
109
110     @Override
111     public List<ServiceInfo> getAllServicesInfo() {
112         return dataAccessService.getList(ServiceInfo.class, filterByCreationDateAndNotDeleted(), orderByCreatedDateAndStatus(), null);
113     }
114
115     private String filterByCreationDateAndNotDeleted() {
116         LocalDateTime minus3Months = LocalDateTime.now().minusMonths(3);
117         Timestamp filterDate = Timestamp.valueOf(minus3Months);
118         return " where" +
119                 "   hidden = false" +
120                 "   and deleted_at is null" +  // don't fetch deleted
121                 "   and created >= '" + filterDate + "' ";
122     }
123
124     private String orderByCreatedDateAndStatus() {
125         return " createdBulkDate DESC ,\n" +
126                 "  (CASE jobStatus\n" +
127                 "   WHEN 'COMPLETED' THEN 0\n" +
128                 "   WHEN 'FAILED' THEN 0\n" +
129                 "   WHEN 'COMPLETED_WITH_ERRORS' THEN 0\n" +
130                 "   WHEN 'IN_PROGRESS' THEN 1\n" +
131                 "   WHEN 'PAUSE' THEN 2\n" +
132                 "   WHEN 'PENDING' THEN 3\n" +
133                 "   WHEN 'STOPPED' THEN 3 END),\n" +
134                 "  statusModifiedDate ";
135     }
136
137     JobType getJobType(ServiceInstantiation request) {
138         if (request.isALaCarte()) {
139             switch (defaultIfNull(request.getAction(), Action.Create)) {
140                 case Delete:
141                     return JobType.ALaCarteService;
142                 case None:
143                     return JobType.ALaCarteService;
144                 default:
145                     return JobType.ALaCarteServiceInstantiation;
146             }
147         } else {
148             return JobType.MacroServiceInstantiation;
149         }
150     }
151
152     @Override
153     public List<UUID> pushBulkJob(ServiceInstantiation request, String userId) {
154         List<UUID> uuids = new ArrayList<>();
155         Date createdBulkDate = Calendar.getInstance().getTime();
156         int bulkSize = request.getBulkSize();
157         UUID templateId = UUID.randomUUID();
158         for (int i = 0; i < bulkSize; i++) {
159             ServiceInfo.ServiceAction serviceAction = getAction(request);
160             JobType jobType = getJobType(request);
161             final String optimisticUniqueServiceInstanceName = getOptimisticUniqueServiceInstanceName(request);
162             Job job = jobAdapter.createServiceInstantiationJob(jobType, request, templateId, userId, optimisticUniqueServiceInstanceName, i);
163             UUID jobId = jobService.add(job);
164             dataAccessService.saveDomainObject(createServiceInfo(userId, request, jobId, templateId, createdBulkDate, optimisticUniqueServiceInstanceName, serviceAction), DaoUtils.getPropsMap());
165             auditVidStatus(jobId, job.getStatus());
166             uuids.add(jobId);
167         }
168         return uuids;
169     }
170
171     private ServiceInfo.ServiceAction getAction(ServiceInstantiation request) {
172         if (request.getAction() == null) {
173             //throw new GenericUncheckedException("Required 'action' field not provided at service level");
174             return Action.Create.getServiceAction();
175         }
176         return request.getAction().getServiceAction();
177     }
178
179
180     private String getOptimisticUniqueServiceInstanceName(ServiceInstantiation request) {
181         return StringUtils.isNotEmpty(request.getInstanceName()) ? getUniqueNameFromDbOnly(request.getInstanceName()) : request.getInstanceName();
182     }
183
184     protected ServiceInfo createServiceInfo(String userId, ServiceInstantiation serviceInstantiation, UUID jobId, UUID templateId, Date createdBulkDate, String optimisticUniqueServiceInstanceName, ServiceInfo.ServiceAction serviceAction) {
185         return new ServiceInfo(
186                 userId,
187                 serviceInstantiation.isALaCarte(),
188                 Job.JobStatus.PENDING, serviceInstantiation.isPause(), jobId, templateId,
189                 serviceInstantiation.getOwningEntityId(),
190                 serviceInstantiation.getOwningEntityName(),
191                 serviceInstantiation.getProjectName(),
192                 serviceInstantiation.getAicZoneId(),
193                 serviceInstantiation.getAicZoneName(),
194                 serviceInstantiation.getTenantId(),
195                 serviceInstantiation.getTenantName(),
196                 serviceInstantiation.getLcpCloudRegionId(),
197                 null,
198                 serviceInstantiation.getSubscriptionServiceType(),
199                 serviceInstantiation.getSubscriberName(),
200                 serviceInstantiation.getGlobalSubscriberId(),
201                 serviceInstantiation.getInstanceId(),
202                 optimisticUniqueServiceInstanceName,
203                 serviceInstantiation.getModelInfo().getModelVersionId(),
204                 serviceInstantiation.getModelInfo().getModelName(),
205                 serviceInstantiation.getModelInfo().getModelVersion(),
206                 createdBulkDate,
207                 serviceAction
208         );
209     }
210
211
212     @Override
213     public RequestDetailsWrapper<ServiceInstantiationRequestDetails> generateMacroServiceInstantiationRequest(UUID jobId, ServiceInstantiation payload, String optimisticUniqueServiceInstanceName, String userId) {
214         String serviceInstanceName = generateServiceName(jobId, payload, optimisticUniqueServiceInstanceName);
215
216         List<ServiceInstantiationService> serviceInstantiationServiceList = generateServiceInstantiationServicesList(payload, serviceInstanceName, createServiceInstantiationVnfList(payload));
217
218         RequestParameters requestParameters = new RequestParameters(payload.getSubscriptionServiceType(), false, serviceInstantiationServiceList);
219
220         ServiceInstantiationRequestDetails requestDetails = generateServiceInstantiationRequestDetails(payload,requestParameters,serviceInstanceName, userId);
221
222         RequestDetailsWrapper<ServiceInstantiationRequestDetails> requestDetailsWrapper = new RequestDetailsWrapper<>(requestDetails);
223         debugRequestDetails(requestDetailsWrapper, logger);
224
225         return requestDetailsWrapper;
226     }
227
228     @Override
229     public RequestDetailsWrapper<ServiceInstantiationRequestDetails> generateALaCarteServiceInstantiationRequest(UUID jobId, ServiceInstantiation payload, String optimisticUniqueServiceInstanceName, String userId) {
230         String serviceInstanceName = generateServiceName(jobId, payload, optimisticUniqueServiceInstanceName);
231
232         List<UserParamNameAndValue> userParams = generateUserParamList();
233
234         RequestParameters requestParameters = new RequestParameters(payload.getSubscriptionServiceType(), true, userParams, payload.getTestApi());
235
236         ServiceInstantiationRequestDetails requestDetails = generateServiceInstantiationRequestDetails(payload,requestParameters,serviceInstanceName, userId);
237
238         RequestDetailsWrapper<ServiceInstantiationRequestDetails> requestDetailsWrapper = new RequestDetailsWrapper<>(requestDetails);
239         debugRequestDetails(requestDetailsWrapper, logger);
240         return requestDetailsWrapper;
241     }
242
243
244     @Override
245     public RequestDetailsWrapper<ServiceDeletionRequestDetails> generateALaCarteServiceDeletionRequest(UUID jobId, ServiceInstantiation payload, String userId){
246
247         ServiceDeletionRequestDetails.RequestParameters requestParameters = new ServiceDeletionRequestDetails.RequestParameters( true, payload.getTestApi());
248
249         ServiceDeletionRequestDetails.RequestInfo requestInfo = new ServiceDeletionRequestDetails.RequestInfo(
250                 VID_SOURCE,
251                 userId);
252
253         ServiceDeletionRequestDetails requestDetails = new ServiceDeletionRequestDetails(payload.getModelInfo(), requestInfo, requestParameters);
254
255         RequestDetailsWrapper<ServiceDeletionRequestDetails> requestDetailsWrapper = new RequestDetailsWrapper<>(requestDetails);
256         debugRequestDetails(requestDetailsWrapper, logger);
257         return requestDetailsWrapper;
258     }
259
260     @Override
261     public RequestDetailsWrapper<VnfInstantiationRequestDetails> generateVnfInstantiationRequest(Vnf vnfDetails, ModelInfo serviceModelInfo, String serviceInstanceId, String userId) {
262
263         VnfInstantiationRequestDetails.RequestInfo requestInfo = new VnfInstantiationRequestDetails.RequestInfo(
264                 getUniqueNameIfNeeded(vnfDetails.getInstanceName(), ResourceType.GENERIC_VNF),
265                 vnfDetails.getProductFamilyId(),
266                 VID_SOURCE,
267                 vnfDetails.isRollbackOnFailure(),
268                 userId);
269         CloudConfiguration cloudConfiguration = generateCloudConfiguration(vnfDetails.getLcpCloudRegionId(), vnfDetails.getTenantId());
270         VnfInstantiationRequestDetails.Platform platform = new VnfInstantiationRequestDetails.Platform(vnfDetails.getPlatformName());
271         VnfInstantiationRequestDetails.LineOfBusiness lineOfBusiness = new VnfInstantiationRequestDetails.LineOfBusiness(vnfDetails.getLineOfBusiness());
272         VnfInstantiationRequestDetails.RequestParameters requestParameters = new VnfInstantiationRequestDetails.RequestParameters(generateUserParamList());
273         VnfInstantiationRequestDetails.RelatedInstance serviceInstance = new VnfInstantiationRequestDetails.RelatedInstance(serviceModelInfo, serviceInstanceId);
274         List<VnfInstantiationRequestDetails.RelatedInstance> relatedInstanceList = new ArrayList<>();
275         relatedInstanceList.add(serviceInstance);
276         return new RequestDetailsWrapper<>(new VnfInstantiationRequestDetails(vnfDetails.getModelInfo(), cloudConfiguration, requestInfo, platform, lineOfBusiness, relatedInstanceList, requestParameters));
277     }
278
279     @Override
280     public RequestDetailsWrapper<VfModuleInstantiationRequestDetails> generateVfModuleInstantiationRequest(VfModule vfModuleDetails, ModelInfo serviceModelInfo, String serviceInstanceId, ModelInfo vnfModelInfo, String vnfInstanceId, String vgInstanceId, String userId) {
281
282         VfModuleInstantiationRequestDetails.RequestInfo requestInfo = new VfModuleInstantiationRequestDetails.RequestInfo(
283                 getUniqueNameIfNeeded(vfModuleDetails.getInstanceName(), ResourceType.VF_MODULE),
284                 null,
285                 VID_SOURCE,
286                 vfModuleDetails.isRollbackOnFailure(),
287                 userId);
288
289         //cloud configuration
290         CloudConfiguration cloudConfiguration = generateCloudConfiguration(vfModuleDetails.getLcpCloudRegionId(), vfModuleDetails.getTenantId());
291
292         //request parameters
293         List<UserParamMap<String, String>> userParams = aggregateAllInstanceParams(extractActualInstanceParams(vfModuleDetails.getInstanceParams()), vfModuleDetails.getSupplementaryParams());
294         RequestParametersVfModule requestParameters = new RequestParametersVfModule(userParams, vfModuleDetails.isUsePreload());
295
296         //related instance list
297         VfModuleInstantiationRequestDetails.RelatedInstance serviceInstance = new VfModuleInstantiationRequestDetails.RelatedInstance(serviceModelInfo, serviceInstanceId);
298         VfModuleInstantiationRequestDetails.RelatedInstance vnfInstance = new VfModuleInstantiationRequestDetails.RelatedInstance(vnfModelInfo, vnfInstanceId);
299         List<VfModuleInstantiationRequestDetails.RelatedInstance> relatedInstanceList = new ArrayList<>();
300         relatedInstanceList.add(serviceInstance);
301         relatedInstanceList.add(vnfInstance);
302         if (vgInstanceId != null) {
303             ModelInfo volumeGroupModel = new ModelInfo();
304             volumeGroupModel.setModelType("volumeGroup");
305             VfModuleInstantiationRequestDetails.RelatedInstance volumeGroupInstance = new VfModuleInstantiationRequestDetails.RelatedInstance(volumeGroupModel, vgInstanceId, vfModuleDetails.getVolumeGroupInstanceName());
306             relatedInstanceList.add(volumeGroupInstance);
307         }
308
309         return new RequestDetailsWrapper<>(new VfModuleInstantiationRequestDetails(vfModuleDetails.getModelInfo(), cloudConfiguration, requestInfo, relatedInstanceList, requestParameters));
310     }
311
312     protected CloudConfiguration generateCloudConfiguration(String lcpCloudRegionId, String tenantId) {
313         CloudConfiguration cloudConfiguration = new CloudConfiguration();
314         cloudConfiguration.setLcpCloudRegionId(lcpCloudRegionId);
315         cloudConfiguration.setTenantId(tenantId);
316         cloudOwnerService.enrichCloudConfigurationWithCloudOwner(cloudConfiguration, lcpCloudRegionId);
317         return cloudConfiguration;
318     }
319
320     @Override
321     public RequestDetailsWrapper<VolumeGroupRequestDetails> generateVolumeGroupInstantiationRequest(VfModule vfModuleDetails, ModelInfo serviceModelInfo, String serviceInstanceId, ModelInfo vnfModelInfo, String vnfInstanceId, String userId) {
322         VolumeGroupRequestDetails.RequestInfo requestInfo = new VolumeGroupRequestDetails.RequestInfo(
323                 getUniqueNameIfNeeded(vfModuleDetails.getVolumeGroupInstanceName(), ResourceType.VOLUME_GROUP),
324                 null,
325                 VID_SOURCE,
326                 vfModuleDetails.isRollbackOnFailure(),
327                 userId);
328         CloudConfiguration cloudConfiguration = generateCloudConfiguration(vfModuleDetails.getLcpCloudRegionId(), vfModuleDetails.getTenantId());
329
330         List<UserParamMap<String, String>> userParams = aggregateAllInstanceParams(extractActualInstanceParams(vfModuleDetails.getInstanceParams()), vfModuleDetails.getSupplementaryParams());
331         RequestParametersVfModule requestParameters = new RequestParametersVfModule(userParams, vfModuleDetails.isUsePreload());
332
333         VfModuleInstantiationRequestDetails.RelatedInstance serviceInstance = new VfModuleInstantiationRequestDetails.RelatedInstance(serviceModelInfo, serviceInstanceId);
334         VfModuleInstantiationRequestDetails.RelatedInstance vnfInstance = new VfModuleInstantiationRequestDetails.RelatedInstance(vnfModelInfo, vnfInstanceId);
335         List<VfModuleInstantiationRequestDetails.RelatedInstance> relatedInstancs = ImmutableList.of(serviceInstance, vnfInstance);
336
337         ModelInfo modelInfo = vfModuleDetails.getModelInfo();
338         modelInfo.setModelType("volumeGroup");
339         return new RequestDetailsWrapper<>(new VolumeGroupRequestDetails(modelInfo, cloudConfiguration, requestInfo, relatedInstancs, requestParameters));
340     }
341
342     protected List<UserParamMap<String, String>> aggregateAllInstanceParams(Map<String, String> instanceParams, Map<String, String> supplementaryParams) {
343         Map<String, String> instanceParamsFinal = defaultIfNull(instanceParams, new HashMap<>());
344         Map<String, String> supplementaryParamsFinal = defaultIfNull(supplementaryParams, new HashMap<>());
345
346         if (!(instanceParamsFinal.isEmpty() && supplementaryParamsFinal.isEmpty())) {
347             //remove duplicate keys from instanceParams if exist in supplementaryParams
348             instanceParamsFinal = instanceParams.entrySet().stream().filter(m->
349                     !supplementaryParamsFinal.containsKey(m.getKey())
350             ).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
351
352             //aggregate the 2 collections and format them as UserParamMap
353             UserParamMap<String, String> aggregatedParams = new UserParamMap<>();
354             aggregatedParams.putAll(instanceParamsFinal);
355             aggregatedParams.putAll(supplementaryParamsFinal);
356
357             return ImmutableList.of(aggregatedParams);
358         }
359
360         return Collections.emptyList();
361     }
362
363     @Override
364     public RequestDetailsWrapper<NetworkInstantiationRequestDetails> generateNetworkInstantiationRequest(Network networkDetails, ModelInfo serviceModelInfo, String serviceInstanceId, String userId) {
365
366         NetworkInstantiationRequestDetails.RequestInfo requestInfo = new NetworkInstantiationRequestDetails.RequestInfo(
367                 getUniqueNameIfNeeded(networkDetails.getInstanceName(), ResourceType.L3_NETWORK),
368                 networkDetails.getProductFamilyId(),
369                 VID_SOURCE,
370                 networkDetails.isRollbackOnFailure(),
371                 userId);
372         CloudConfiguration cloudConfiguration = generateCloudConfiguration(networkDetails.getLcpCloudRegionId(), networkDetails.getTenantId());
373         NetworkInstantiationRequestDetails.Platform platform = new NetworkInstantiationRequestDetails.Platform(networkDetails.getPlatformName());
374         NetworkInstantiationRequestDetails.LineOfBusiness lineOfBusiness = new NetworkInstantiationRequestDetails.LineOfBusiness(networkDetails.getLineOfBusiness());
375         NetworkInstantiationRequestDetails.RequestParameters requestParameters = new NetworkInstantiationRequestDetails.RequestParameters(generateUserParamList());
376         NetworkInstantiationRequestDetails.RelatedInstance serviceInstance = new NetworkInstantiationRequestDetails.RelatedInstance(serviceModelInfo, serviceInstanceId);
377         List<NetworkInstantiationRequestDetails.RelatedInstance> relatedInstanceList = new ArrayList<>();
378         relatedInstanceList.add(serviceInstance);
379         return new RequestDetailsWrapper<>(new NetworkInstantiationRequestDetails(networkDetails.getModelInfo(), cloudConfiguration, requestInfo, platform, lineOfBusiness, relatedInstanceList, requestParameters));
380     }
381
382     @Override
383     public RequestDetailsWrapper<InstanceGroupInstantiationRequestDetails> generateInstanceGroupInstantiationRequest(InstanceGroup instanceGroupDetails, ModelInfo serviceModelInfo, String serviceInstanceId, String userId) {
384         InstanceGroupInstantiationRequestDetails.RequestInfo requestInfo = new InstanceGroupInstantiationRequestDetails.RequestInfo(
385                 getUniqueNameIfNeeded(instanceGroupDetails.getInstanceName(), ResourceType.INSTANCE_GROUP),
386                 null,
387                 "VID",
388                 instanceGroupDetails.isRollbackOnFailure(),
389                 userId);
390         InstanceGroupInstantiationRequestDetails.RequestParameters requestParameters = new InstanceGroupInstantiationRequestDetails.RequestParameters(generateUserParamList());
391         InstanceGroupInstantiationRequestDetails.RelatedInstance serviceInstance = new InstanceGroupInstantiationRequestDetails.RelatedInstance(serviceModelInfo, serviceInstanceId);
392         List<InstanceGroupInstantiationRequestDetails.RelatedInstance> relatedInstanceList = ImmutableList.of(serviceInstance);
393         return new RequestDetailsWrapper<>(new InstanceGroupInstantiationRequestDetails(instanceGroupDetails.getModelInfo(), requestInfo, relatedInstanceList, requestParameters));
394     }
395
396     // TODO
397     private List<UserParamNameAndValue> generateUserParamList() {
398         return Collections.emptyList();
399     }
400
401     protected List<ServiceInstantiationService> generateServiceInstantiationServicesList(ServiceInstantiation payload, String serviceInstanceName, ServiceInstantiationVnfList vnfList) {
402         List<ServiceInstantiationService> serviceInstantiationServiceList = new LinkedList<>();
403         List<Map<String, String>> unFilteredInstanceParams = defaultIfNull(payload.getInstanceParams(), Collections.emptyList());
404         List<Map<String, String>> filteredInstanceParams = removeUnNeededParams(unFilteredInstanceParams);
405         ServiceInstantiationService serviceInstantiationService = new ServiceInstantiationService(
406                 payload.getModelInfo(),
407                 serviceInstanceName,
408                 filteredInstanceParams,
409                 vnfList
410         );
411         serviceInstantiationServiceList.add(serviceInstantiationService);
412         return serviceInstantiationServiceList;
413     }
414
415     private ServiceInstantiationRequestDetails generateServiceInstantiationRequestDetails(ServiceInstantiation payload, RequestParameters requestParameters, String serviceInstanceName, String userId) {
416         ServiceInstantiationRequestDetails.RequestInfo requestInfo = new ServiceInstantiationRequestDetails.RequestInfo(serviceInstanceName,
417                 payload.getProductFamilyId(),
418                 VID_SOURCE,
419                 payload.isRollbackOnFailure(),
420                 userId);
421         ServiceInstantiationOwningEntity owningEntity = new ServiceInstantiationOwningEntity(payload.getOwningEntityId(), payload.getOwningEntityName());
422         SubscriberInfo subscriberInfo = generateSubscriberInfo(payload);
423         Project project = payload.getProjectName() != null ?  new Project(payload.getProjectName()) : null;
424         return new ServiceInstantiationRequestDetails(payload.getModelInfo(), owningEntity, subscriberInfo, project, requestInfo, requestParameters);
425     }
426
427
428     protected SubscriberInfo generateSubscriberInfo(ServiceInstantiation payload) {
429         SubscriberInfo subscriberInfo = new SubscriberInfo();
430         subscriberInfo.setGlobalSubscriberId(payload.getGlobalSubscriberId());
431         return subscriberInfo;
432     }
433
434     protected String generateServiceName(UUID jobId, ServiceInstantiation payload, String optimisticUniqueServiceInstanceName) {
435         String serviceInstanceName = null;
436         if(StringUtils.isNotEmpty(optimisticUniqueServiceInstanceName)) {
437             serviceInstanceName = peekServiceName(jobId, payload, optimisticUniqueServiceInstanceName);
438         }
439         return serviceInstanceName;
440     }
441
442     protected String peekServiceName(UUID jobId, ServiceInstantiation payload, String optimisticUniqueServiceInstanceName) {
443         String serviceInstanceName;
444         // unique name already exist in service info. If it's free in AAI we use it
445         if (isNameFreeInAai(optimisticUniqueServiceInstanceName, ResourceType.SERVICE_INSTANCE)) {
446             serviceInstanceName =  optimisticUniqueServiceInstanceName;
447         }
448         //otherwise we used the original service instance name (from payload) to get a new unique name from DB and AAI
449         else {
450             serviceInstanceName = getUniqueName(payload.getInstanceName(), ResourceType.SERVICE_INSTANCE);
451         }
452
453         //update serviceInfo with new name if needed
454         try {
455             updateServiceInfo(jobId, x -> x.setServiceInstanceName(serviceInstanceName));
456         } catch (Exception e) {
457             logger.error("Failed updating service name {} in serviceInfo", serviceInstanceName, e);
458         }
459
460         return serviceInstanceName;
461     }
462
463     @Override
464     public List<Map<String,String>> buildVnfInstanceParams(List<Map<String, String>> currentVnfInstanceParams, List<VfModuleMacro> vfModules){
465         List<Map<String, String>> filteredVnfInstanceParams = removeUnNeededParams(currentVnfInstanceParams);
466
467         if (!featureManager.isActive(Features.FLAG_SHIFT_VFMODULE_PARAMS_TO_VNF)) {
468             return filteredVnfInstanceParams;
469         }
470
471         Map<String,String> vnfInstanceParams = extractActualInstanceParams(filteredVnfInstanceParams);
472         vfModules.stream()
473                 .map(x->extractActualInstanceParams(x.getInstanceParams()))
474                 .forEach(vnfInstanceParams::putAll);
475         return vnfInstanceParams.isEmpty() ? Collections.emptyList() : ImmutableList.of(vnfInstanceParams);
476     }
477
478     //Make sure we always get a one Map from InstanceParams
479     private Map<String, String> extractActualInstanceParams(List<Map<String, String>> originalInstanceParams) {
480         if (originalInstanceParams==null || originalInstanceParams.isEmpty() || originalInstanceParams.get(0)==null) {
481             return new HashMap<>();
482         }
483         return originalInstanceParams.get(0);
484     }
485
486     private List<Map<String, String>> removeUnNeededParams(List<Map<String, String>> instanceParams) {
487         List<String> keysToRemove = new ArrayList<>();
488         if (instanceParams == null || instanceParams.isEmpty()) {
489             return Collections.emptyList();
490         }
491
492         for (String key : instanceParams.get(0).keySet()) {
493             for (String paramToIgnore : PARAMS_TO_IGNORE)
494                 if ((key.equalsIgnoreCase(paramToIgnore))) {
495                     keysToRemove.add(key);
496                 }
497         }
498
499         Map<String, String> result = instanceParams.get(0).entrySet().stream()
500                 .filter(entry->!keysToRemove.contains(entry.getKey()))
501                 .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
502
503         return result.isEmpty() ?  Collections.emptyList() : Collections.singletonList(result);
504     }
505
506     private ServiceInstantiationVnfList createServiceInstantiationVnfList(ServiceInstantiation payload) {
507         CloudConfiguration cloudConfiguration = generateCloudConfiguration(payload.getLcpCloudRegionId(), payload.getTenantId());
508
509         Map<String, Vnf> vnfs = payload.getVnfs();
510         List<ServiceInstantiationVnf> vnfList = new ArrayList<>();
511         for (Vnf vnf : vnfs.values()) {
512             Map<String, Map<String, VfModule>> vfModules = vnf.getVfModules();
513             List<VfModuleMacro> convertedUnFilteredVfModules = convertVfModuleMapToList(vfModules);
514             List<VfModuleMacro> filteredVfModules = filterInstanceParamsFromVfModuleAndUniqueNames(convertedUnFilteredVfModules);
515             ServiceInstantiationVnf serviceInstantiationVnf = new ServiceInstantiationVnf(
516                     vnf.getModelInfo(),
517                     cloudConfiguration,
518                     vnf.getPlatformName(),
519                     vnf.getLineOfBusiness(),
520                     payload.getProductFamilyId(),
521                     buildVnfInstanceParams(vnf.getInstanceParams(), filteredVfModules),
522                     filteredVfModules,
523                     getUniqueNameIfNeeded(vnf.getInstanceName(), ResourceType.GENERIC_VNF)
524             );
525             vnfList.add(serviceInstantiationVnf);
526         }
527
528         return new ServiceInstantiationVnfList(vnfList);
529     }
530
531     private List<VfModuleMacro> convertVfModuleMapToList(Map<String, Map<String, VfModule>> vfModules) {
532         ObjectMapper mapper = new ObjectMapper();
533         return vfModules.values().stream().flatMap(vfModule ->
534                 vfModule.values().stream().map(item -> {
535                     List<UserParamMap<String, String>> aggregatedParams = aggregateAllInstanceParams(extractActualInstanceParams(item.getInstanceParams()), item.getSupplementaryParams());
536                     List<Map<String, String>> aggregatedParamsConverted = mapper.convertValue(aggregatedParams, new TypeReference<List<Map>>(){});
537
538                     return new VfModuleMacro(
539                             item.getModelInfo(),
540                             item.getInstanceName(),
541                             item.getVolumeGroupInstanceName(),
542                             aggregatedParamsConverted);
543                     }
544                 )
545         ).collect(Collectors.toList());
546     }
547
548     private List<VfModuleMacro> filterInstanceParamsFromVfModuleAndUniqueNames(List<VfModuleMacro> unFilteredVfModules) {
549         return unFilteredVfModules.stream().map(vfModule ->
550                 new VfModuleMacro(
551                         vfModule.getModelInfo(),
552                         getUniqueNameIfNeeded(vfModule.getInstanceName(), ResourceType.VF_MODULE),
553                         getUniqueNameIfNeeded(vfModule.getVolumeGroupInstanceName(), ResourceType.VOLUME_GROUP),
554                         removeUnNeededParams(vfModule.getInstanceParams())))
555                 .collect(Collectors.toList());
556     }
557
558     private String getUniqueNameIfNeeded(String name, ResourceType resourceType) {
559         return StringUtils.isNotEmpty(name) ? getUniqueName(name, resourceType) : null;
560     }
561
562     @Override
563     public String getServiceInstantiationPath(ServiceInstantiation serviceInstantiationRequest) {
564         //in case pause flag is true - use assign , else - use create.
565         return MsoBusinessLogicImpl.validateEndpointPath(
566                 serviceInstantiationRequest.isPause() ?
567                         MsoProperties.MSO_REST_API_SERVICE_INSTANCE_ASSIGN : MsoProperties.MSO_REST_API_SERVICE_INSTANCE_CREATE
568         );
569     }
570
571     @Override
572     public String getServiceDeletionPath(String serviceInstanceId) {
573         return MsoBusinessLogicImpl.validateEndpointPath( MsoProperties.MSO_DELETE_OR_UNASSIGN_REST_API_SVC_INSTANCE)  + "/" + serviceInstanceId;
574     }
575
576     @Override
577     public String getVnfInstantiationPath(String serviceInstanceId) {
578         return MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_VNF_INSTANCE).
579                 replaceFirst(SVC_INSTANCE_ID, serviceInstanceId);
580     }
581
582     @Override
583     public String getNetworkInstantiationPath(String serviceInstanceId) {
584         return MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_NETWORK_INSTANCE).
585                 replaceFirst(SVC_INSTANCE_ID, serviceInstanceId);
586     }
587
588     @Override
589     public String getVfmoduleInstantiationPath(String serviceInstanceId, String vnfInstanceId) {
590         return MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_VF_MODULE_INSTANCE)
591                 .replaceFirst(SVC_INSTANCE_ID, serviceInstanceId)
592                 .replaceFirst(VNF_INSTANCE_ID, vnfInstanceId);
593     }
594
595     @Override
596     public String getVolumeGroupInstantiationPath(String serviceInstanceId, String vnfInstanceId) {
597         return MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_VOLUME_GROUP_INSTANCE)
598                 .replaceFirst(SVC_INSTANCE_ID, serviceInstanceId)
599                 .replaceFirst(VNF_INSTANCE_ID, vnfInstanceId);
600     }
601
602     @Override
603     public String getInstanceGroupInstantiationPath() {
604         return MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_INSTANCE_GROUP);
605     }
606
607     @Override
608     public String getInstanceGroupDeletePath(String instanceGroupId) {
609         return MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_INSTANCE_GROUP)
610                 + '/' + instanceGroupId;
611     }
612
613     @Override
614     public String getOrchestrationRequestsPath() {
615         return MsoBusinessLogicImpl.validateEndpointPath(MsoProperties.MSO_REST_API_GET_ORC_REQ);
616     }
617
618     @Override
619     public ServiceInfo updateServiceInfo(UUID jobUUID, Consumer<ServiceInfo> serviceUpdater) {
620         ServiceInfo serviceInfo = getServiceInfoByJobId(jobUUID);
621         serviceUpdater.accept(serviceInfo);
622         dataAccessService.saveDomainObject(serviceInfo, DaoUtils.getPropsMap());
623         return serviceInfo;
624     }
625
626     @Override
627     public ServiceInfo updateServiceInfoAndAuditStatus(UUID jobUuid, JobStatus jobStatus) {
628         auditVidStatus(jobUuid,jobStatus);
629         return updateServiceInfo(jobUuid, x -> setServiceInfoStatus(x, jobStatus));
630     }
631
632     private void setServiceInfoStatus(ServiceInfo serviceInfo, JobStatus jobStatus) {
633         serviceInfo.setJobStatus(jobStatus);
634         serviceInfo.setStatusModifiedDate(new Date());
635     }
636
637     public ServiceInfo getServiceInfoByJobId(UUID jobUUID) {
638         List<ServiceInfo> serviceInfoList = dataAccessService.getList(ServiceInfo.class, String.format(" where jobId = '%s' ", jobUUID), null, null);
639         if (serviceInfoList.size() != 1) {
640             throw new GenericUncheckedException("Failed to retrieve job with uuid " + jobUUID + " from ServiceInfo table. Instances found: " + serviceInfoList.size());
641         }
642         return serviceInfoList.get(0);
643     }
644
645     public List<JobAuditStatus> getAuditStatuses(UUID jobUUID, JobAuditStatus.SourceStatus source) {
646         return dataAccessService.getList(
647             JobAuditStatus.class,
648             String.format(" where SOURCE = '%s' and JOB_ID = '%s'",source, jobUUID),
649             " CREATED_DATE ", null);
650     }
651
652     private JobAuditStatus getLatestAuditStatus(UUID jobUUID, JobAuditStatus.SourceStatus source){
653         List<JobAuditStatus> list = getAuditStatuses(jobUUID,source);
654         return !list.isEmpty() ? list.get(list.size()-1) : null;
655     }
656
657     @Override
658     public void auditVidStatus(UUID jobUUID, JobStatus jobStatus){
659         JobAuditStatus vidStatus = new JobAuditStatus(jobUUID, jobStatus.toString(), JobAuditStatus.SourceStatus.VID);
660         auditStatus(vidStatus);
661     }
662
663     @Override
664     public void auditMsoStatus(UUID jobUUID, AsyncRequestStatus.Request msoRequestStatus){
665         auditMsoStatus(jobUUID, msoRequestStatus.requestStatus.getRequestState(), msoRequestStatus.requestId, msoRequestStatus.requestStatus.getStatusMessage());
666     }
667
668     @Override
669     public void auditMsoStatus(UUID jobUUID, String jobStatus, String requestId, String additionalInfo){
670         JobAuditStatus msoStatus = new JobAuditStatus(jobUUID, jobStatus, JobAuditStatus.SourceStatus.MSO,
671                 requestId != null ? UUID.fromString(requestId) : null,
672                 additionalInfo);
673         auditStatus(msoStatus);
674     }
675
676     private void auditStatus(JobAuditStatus jobAuditStatus){
677         JobAuditStatus latestStatus = getLatestAuditStatus(jobAuditStatus.getJobId(), jobAuditStatus.getSource());
678         if (latestStatus == null || !latestStatus.equals(jobAuditStatus))
679             dataAccessService.saveDomainObject(jobAuditStatus, DaoUtils.getPropsMap());
680
681     }
682
683     public Job.JobStatus calcStatus(AsyncRequestStatus asyncRequestStatus) {
684         String msoRequestState = asyncRequestStatus.request.requestStatus.getRequestState().toLowerCase().replaceAll("[^a-z]+", "");
685         JobStatus jobStatus = msoStateToJobStatusMap.get(msoRequestState);
686         return (jobStatus != null ? jobStatus : JobStatus.IN_PROGRESS);
687     }
688
689     @Override
690     public void handleFailedInstantiation(UUID jobUUID) {
691         ServiceInfo serviceInfo = updateServiceInfoAndAuditStatus(jobUUID, JobStatus.FAILED);
692         List<ServiceInfo> serviceInfoList = dataAccessService.getList(
693                 ServiceInfo.class,
694                 String.format(" where templateId = '%s' and jobStatus = '%s'",
695                         serviceInfo.getTemplateId(),
696                         JobStatus.PENDING),
697                 null, null);
698         serviceInfoList.forEach(si -> updateServiceInfoAndAuditStatus(si.getJobId(), JobStatus.STOPPED));
699     }
700
701     @Override
702     public void deleteJob(UUID jobId) {
703         jobService.delete(jobId);
704         Date now = new Date();
705         updateServiceInfo(jobId, x -> x.setDeletedAt(now));
706     }
707
708     @Override
709     public void hideServiceInfo(UUID jobUUID) {
710         ServiceInfo serviceInfo = getServiceInfoByJobId(jobUUID);
711         if (!serviceInfo.getJobStatus().isFinal()) {
712             String message = String.format( "jobId %s: Service status does not allow hide service, status = %s",
713                     serviceInfo.getJobId(),
714                     serviceInfo.getJobStatus());
715             logger.error(EELFLoggerDelegate.errorLogger, message);
716             throw new OperationNotAllowedException(message);
717         }
718         serviceInfo.setHidden(true);
719         dataAccessService.saveDomainObject(serviceInfo, DaoUtils.getPropsMap());
720     }
721
722     @Override
723     public int getCounterForName(String name) {
724
725         String hqlSelectNC = "from NameCounter where name = :name";
726         String hqlUpdateCounter = "update NameCounter set counter = :newCounter " +
727                 "where name= :name " +
728                 "and counter= :prevCounter";
729
730         Integer counter = null;
731         GenericUncheckedException lastException = null;
732         for (int i = 0; i< MAX_RETRIES_GETTING_COUNTER && counter==null; i++) {
733             try {
734                 counter = calcCounter(name, hqlSelectNC, hqlUpdateCounter);
735             }
736             catch (GenericUncheckedException exception) {
737                 lastException = exception; //do nothing, we will try again in the loop
738             }
739         }
740
741         if (counter!=null) {
742             return counter;
743         }
744
745         throw lastException!=null ? new DbFailureUncheckedException(lastException) :
746                 new DbFailureUncheckedException("Failed to get counter for "+name+" due to unknown error");
747
748     }
749
750     private Integer calcCounter(String name, String hqlSelectNC, String hqlUpdateCounter) {
751         Integer counter;
752         counter = DaoUtils.tryWithSessionAndTransaction(sessionFactory, session -> {
753             NameCounter nameCounter = (NameCounter) session.createQuery(hqlSelectNC)
754                     .setText("name", name)
755                     .uniqueResult();
756             if (nameCounter != null) {
757                 int updatedRows = session.createQuery(hqlUpdateCounter)
758                         .setText("name", nameCounter.getName())
759                         .setInteger("prevCounter", nameCounter.getCounter())
760                         .setInteger("newCounter", nameCounter.getCounter() + 1)
761                         .executeUpdate();
762                 if (updatedRows == 1) {
763                     return nameCounter.getCounter() + 1;
764                 }
765             } else {
766                 Object nameAsId = session.save(new NameCounter(name));
767                 //if save success
768                 if (nameAsId != null) {
769                     return 0;
770                 }
771             }
772             //in case of failure return null, in order to continue the loop
773             return null;
774         });
775         return counter;
776     }
777
778     @Override
779     public int getMaxRetriesGettingFreeNameFromAai() {
780         return maxRetriesGettingFreeNameFromAai;
781     }
782
783     @Override
784     public void setMaxRetriesGettingFreeNameFromAai(int maxRetriesGettingFreeNameFromAai) {
785         this.maxRetriesGettingFreeNameFromAai = maxRetriesGettingFreeNameFromAai;
786     }
787
788     @Override
789     public String getUniqueName(String name, ResourceType resourceType) {
790         //check that name aai response well before increasing counter from DB
791         //Prevents unnecessary increasing of the counter while AAI doesn't response
792         isNameFreeInAai(NAME_FOR_CHECK_AAI_STATUS, resourceType);
793
794         for (int i=0; i<getMaxRetriesGettingFreeNameFromAai(); i++) {
795             String newName = getUniqueNameFromDbOnly(name);
796             if (isNameFreeInAai(newName, resourceType)) {
797                 return newName;
798             }
799         }
800
801         throw new MaxRetriesException("find unused name for "+name, getMaxRetriesGettingFreeNameFromAai());
802     }
803
804     protected String getUniqueNameFromDbOnly(String name) {
805         int counter = getCounterForName(name);
806         return formatNameAndCounter(name, counter);
807     }
808
809     //the method is protected so we can call it in the UT
810     protected String formatNameAndCounter(String name, int counter) {
811         return counter==0 ? name : name + "_" + String.format("%03d", counter);
812     }
813
814     private boolean isNameFreeInAai(String name, ResourceType resourceType) throws ExceptionWithRequestInfo {
815         return !aaiClient.isNodeTypeExistsByName(name, resourceType);
816     }
817
818 }