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