Merge branch 'recursive-orch'
[so.git] / bpmn / so-bpmn-tasks / src / main / java / org / onap / so / bpmn / infrastructure / workflow / tasks / ebb / loader / ServiceEBBLoader.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP - SO
4  * ================================================================================
5  * Copyright (c) 2020 Nokia
6  * ================================================================================
7  * Modifications Copyright (c) 2021 Orange
8  * ================================================================================
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  * ============LICENSE_END=========================================================
21  */
22
23 package org.onap.so.bpmn.infrastructure.workflow.tasks.ebb.loader;
24
25 import com.fasterxml.jackson.core.JsonProcessingException;
26 import org.camunda.bpm.engine.delegate.DelegateExecution;
27 import org.javatuples.Pair;
28 import org.onap.aai.domain.yang.ComposedResource;
29 import org.onap.aai.domain.yang.ComposedResources;
30 import org.onap.aai.domain.yang.GenericVnf;
31 import org.onap.aai.domain.yang.Relationship;
32 import org.onap.aai.domain.yang.RelationshipData;
33 import org.onap.aai.domain.yang.RelationshipList;
34 import org.onap.aai.domain.yang.ServiceInstance;
35 import org.onap.aai.domain.yang.VpnBinding;
36 import org.onap.aaiclient.client.aai.AAICommonObjectMapperProvider;
37 import org.onap.aaiclient.client.aai.entities.AAIResultWrapper;
38 import org.onap.aaiclient.client.aai.entities.Relationships;
39 import org.onap.aaiclient.client.generated.fluentbuilders.AAIFluentTypeBuilder;
40 import org.onap.so.bpmn.infrastructure.workflow.tasks.Resource;
41 import org.onap.so.bpmn.infrastructure.workflow.tasks.VrfBondingServiceException;
42 import org.onap.so.bpmn.infrastructure.workflow.tasks.WorkflowType;
43 import org.onap.so.bpmn.servicedecomposition.bbobjects.Configuration;
44 import org.onap.so.bpmn.servicedecomposition.bbobjects.VfModule;
45 import org.onap.so.bpmn.servicedecomposition.modelinfo.ModelInfoNetwork;
46 import org.onap.so.bpmn.servicedecomposition.modelinfo.ModelInfoPnf;
47 import org.onap.so.bpmn.servicedecomposition.tasks.BBInputSetup;
48 import org.onap.so.bpmn.servicedecomposition.tasks.BBInputSetupUtils;
49 import org.onap.so.client.exception.ExceptionBuilder;
50 import org.onap.so.client.orchestration.AAIConfigurationResources;
51 import org.onap.so.db.catalog.beans.CollectionNetworkResourceCustomization;
52 import org.onap.so.db.catalog.beans.CollectionResourceCustomization;
53 import org.onap.so.db.catalog.beans.CollectionResourceInstanceGroupCustomization;
54 import org.onap.so.db.catalog.beans.InstanceGroup;
55 import org.onap.so.db.catalog.client.CatalogDbClient;
56 import org.onap.so.serviceinstancebeans.ModelType;
57 import org.onap.so.serviceinstancebeans.RelatedInstance;
58 import org.onap.so.serviceinstancebeans.ServiceInstancesRequest;
59 import org.slf4j.Logger;
60 import org.slf4j.LoggerFactory;
61 import org.springframework.stereotype.Component;
62 import java.io.IOException;
63 import java.util.ArrayList;
64 import java.util.List;
65 import java.util.Map;
66 import java.util.Optional;
67 import static org.onap.so.bpmn.infrastructure.workflow.tasks.WorkflowActionConstants.ACTIVATE_INSTANCE;
68 import static org.onap.so.bpmn.infrastructure.workflow.tasks.WorkflowActionConstants.DEACTIVATE_INSTANCE;
69 import static org.onap.so.bpmn.infrastructure.workflow.tasks.WorkflowActionConstants.DELETE_INSTANCE;
70 import static org.onap.so.bpmn.infrastructure.workflow.tasks.WorkflowActionConstants.UNASSIGN_INSTANCE;
71 import static org.onap.so.bpmn.infrastructure.workflow.tasks.WorkflowActionConstants.UPGRADE_INSTANCE;
72 import static org.onap.so.bpmn.infrastructure.workflow.tasks.WorkflowActionConstants.WORKFLOW_ACTION_ERROR_MESSAGE;
73 import static org.onap.so.bpmn.infrastructure.workflow.tasks.WorkflowActionConstants.CREATE_INSTANCE;
74 import static org.onap.so.bpmn.infrastructure.workflow.tasks.WorkflowActionConstants.FABRIC_CONFIGURATION;
75 import static org.onap.so.bpmn.infrastructure.workflow.tasks.WorkflowActionConstants.NETWORKCOLLECTION;
76 import static org.onap.so.bpmn.infrastructure.workflow.tasks.WorkflowActionConstants.USER_PARAM_SERVICE;
77 import static org.onap.so.bpmn.infrastructure.workflow.tasks.WorkflowActionConstants.ASSIGN_INSTANCE;
78
79
80 @Component
81 public class ServiceEBBLoader {
82
83     private static final Logger logger = LoggerFactory.getLogger(ServiceEBBLoader.class);
84
85     private final UserParamsServiceTraversal userParamsServiceTraversal;
86     private final CatalogDbClient catalogDbClient;
87     private final VrfValidation vrfValidation;
88     private final AAIConfigurationResources aaiConfigurationResources;
89     private final WorkflowActionExtractResourcesAAI workflowActionUtils;
90     private final BBInputSetupUtils bbInputSetupUtils;
91     private final BBInputSetup bbInputSetup;
92     private final ExceptionBuilder exceptionBuilder;
93
94     public ServiceEBBLoader(UserParamsServiceTraversal userParamsServiceTraversal, CatalogDbClient catalogDbClient,
95             VrfValidation vrfValidation, AAIConfigurationResources aaiConfigurationResources,
96             WorkflowActionExtractResourcesAAI workflowActionUtils, BBInputSetupUtils bbInputSetupUtils,
97             BBInputSetup bbInputSetup, ExceptionBuilder exceptionBuilder) {
98         this.userParamsServiceTraversal = userParamsServiceTraversal;
99         this.catalogDbClient = catalogDbClient;
100         this.vrfValidation = vrfValidation;
101         this.aaiConfigurationResources = aaiConfigurationResources;
102         this.workflowActionUtils = workflowActionUtils;
103         this.bbInputSetupUtils = bbInputSetupUtils;
104         this.bbInputSetup = bbInputSetup;
105         this.exceptionBuilder = exceptionBuilder;
106     }
107
108     public List<Resource> getResourceListForService(ServiceInstancesRequest sIRequest, String requestAction,
109             DelegateExecution execution, String serviceInstanceId, String resourceId,
110             List<Pair<WorkflowType, String>> aaiResourceIds) throws IOException, VrfBondingServiceException {
111         boolean containsService = false;
112         List<Resource> resourceList = new ArrayList<>();
113         List<Map<String, Object>> userParams = sIRequest.getRequestDetails().getRequestParameters().getUserParams();
114         if (requestAction.equalsIgnoreCase(ASSIGN_INSTANCE)) {
115             // SERVICE-MACRO-ASSIGN will always get user params with a
116             // service.
117
118             if (userParams != null) {
119                 containsService = isContainsService(sIRequest);
120                 if (containsService) {
121                     resourceList = userParamsServiceTraversal.getResourceListFromUserParams(execution, userParams,
122                             serviceInstanceId, requestAction);
123                 }
124             } else {
125                 buildAndThrowException(execution,
126                         "Service-Macro-Assign request details must contain user params with a service");
127             }
128         } else if (requestAction.equalsIgnoreCase(CREATE_INSTANCE)) {
129             // SERVICE-MACRO-CREATE will get user params with a service,
130             // a service with a network, a service with a
131             // network collection, OR an empty service.
132             // If user params is just a service or null and macro
133             // queries the SI and finds a VNF, macro fails.
134
135             if (userParams != null) {
136                 containsService = isContainsService(sIRequest);
137             }
138             if (containsService) {
139                 resourceList = userParamsServiceTraversal.getResourceListFromUserParams(execution, userParams,
140                         serviceInstanceId, requestAction);
141             }
142             if (!isComposedService(resourceList) && !foundRelated(resourceList)) {
143                 traverseCatalogDbService(execution, sIRequest, resourceList, aaiResourceIds);
144             }
145         } else if ((ACTIVATE_INSTANCE.equalsIgnoreCase(requestAction)
146                 || UNASSIGN_INSTANCE.equalsIgnoreCase(requestAction) || DELETE_INSTANCE.equalsIgnoreCase(requestAction)
147                 || UPGRADE_INSTANCE.equalsIgnoreCase(requestAction)
148                 || requestAction.equalsIgnoreCase("activate" + FABRIC_CONFIGURATION))) {
149             // SERVICE-MACRO-ACTIVATE, SERVICE-MACRO-UNASSIGN, and
150             // SERVICE-MACRO-DELETE
151             // Will never get user params with service, macro will have
152             // to query the SI in AAI to find related instances.
153             traverseAAIService(execution, resourceList, resourceId, aaiResourceIds);
154         } else if (DEACTIVATE_INSTANCE.equalsIgnoreCase(requestAction)) {
155             resourceList.add(new Resource(WorkflowType.SERVICE, "", false, null));
156         }
157         return resourceList;
158     }
159
160     private boolean isContainsService(ServiceInstancesRequest sIRequest) {
161         boolean containsService;
162         List<Map<String, Object>> userParams = sIRequest.getRequestDetails().getRequestParameters().getUserParams();
163         containsService = userParams.stream().anyMatch(param -> param.containsKey(USER_PARAM_SERVICE));
164         return containsService;
165     }
166
167     public void traverseCatalogDbService(DelegateExecution execution, ServiceInstancesRequest sIRequest,
168             List<Resource> resourceList, List<Pair<WorkflowType, String>> aaiResourceIds)
169             throws JsonProcessingException, VrfBondingServiceException {
170         String modelUUID = sIRequest.getRequestDetails().getModelInfo().getModelVersionId();
171         org.onap.so.db.catalog.beans.Service service = catalogDbClient.getServiceByID(modelUUID);
172
173         if (service == null) {
174             buildAndThrowException(execution, "Could not find the service model in catalog db.");
175         } else {
176             Resource serviceResource = new Resource(WorkflowType.SERVICE, service.getModelUUID(), false, null);
177             resourceList.add(serviceResource);
178             RelatedInstance relatedVpnBinding =
179                     bbInputSetupUtils.getRelatedInstanceByType(sIRequest.getRequestDetails(), ModelType.vpnBinding);
180             RelatedInstance relatedLocalNetwork =
181                     bbInputSetupUtils.getRelatedInstanceByType(sIRequest.getRequestDetails(), ModelType.network);
182
183             if (relatedVpnBinding != null && relatedLocalNetwork != null) {
184                 traverseVrfConfiguration(aaiResourceIds, resourceList, serviceResource, service, relatedVpnBinding,
185                         relatedLocalNetwork);
186             } else {
187                 traverseNetworkCollection(execution, resourceList, serviceResource, service);
188             }
189         }
190     }
191
192     public boolean foundRelated(List<Resource> resourceList) {
193         return (containsWorkflowType(resourceList, WorkflowType.VNF)
194                 || containsWorkflowType(resourceList, WorkflowType.PNF)
195                 || containsWorkflowType(resourceList, WorkflowType.NETWORK)
196                 || containsWorkflowType(resourceList, WorkflowType.NETWORKCOLLECTION));
197     }
198
199     public boolean isComposedService(List<Resource> resourceList) {
200         return resourceList.stream().anyMatch(s -> s.getResourceType() == WorkflowType.SERVICE && s.hasParent());
201     }
202
203     public void traverseAAIService(DelegateExecution execution, List<Resource> resourceList, String resourceId,
204             List<Pair<WorkflowType, String>> aaiResourceIds) {
205         try {
206             ServiceInstance serviceInstanceAAI = bbInputSetupUtils.getAAIServiceInstanceById(resourceId);
207             org.onap.so.bpmn.servicedecomposition.bbobjects.ServiceInstance serviceInstanceMSO =
208                     bbInputSetup.getExistingServiceInstance(serviceInstanceAAI);
209             var serviceResource =
210                     new Resource(WorkflowType.SERVICE, serviceInstanceMSO.getServiceInstanceId(), false, null);
211             serviceResource.setModelInvariantId(serviceInstanceAAI.getModelInvariantId());
212             serviceResource.setModelVersionId(serviceInstanceAAI.getModelVersionId());
213             resourceList.add(serviceResource);
214             traverseServiceInstanceChildService(resourceList, serviceResource, serviceInstanceAAI);
215             traverseServiceInstanceMSOVnfs(resourceList, serviceResource, aaiResourceIds, serviceInstanceMSO);
216             traverseServiceInstanceMSOPnfs(resourceList, serviceResource, aaiResourceIds, serviceInstanceMSO);
217             if (serviceInstanceMSO.getNetworks() != null) {
218                 for (org.onap.so.bpmn.servicedecomposition.bbobjects.L3Network network : serviceInstanceMSO
219                         .getNetworks()) {
220                     aaiResourceIds.add(new Pair<>(WorkflowType.NETWORK, network.getNetworkId()));
221                     Resource networkResource =
222                             new Resource(WorkflowType.NETWORK, network.getNetworkId(), false, serviceResource);
223                     ModelInfoNetwork modelInfoNetwork = network.getModelInfoNetwork();
224                     if (modelInfoNetwork != null) {
225                         networkResource.setModelCustomizationId(modelInfoNetwork.getModelCustomizationUUID());
226                         networkResource.setModelVersionId(modelInfoNetwork.getModelUUID());
227                         networkResource.setModelCustomizationId(modelInfoNetwork.getModelCustomizationUUID());
228                     }
229                     resourceList.add(networkResource);
230                 }
231             }
232             if (serviceInstanceMSO.getCollection() != null) {
233                 logger.debug("found networkcollection");
234                 aaiResourceIds
235                         .add(new Pair<>(WorkflowType.NETWORKCOLLECTION, serviceInstanceMSO.getCollection().getId()));
236                 resourceList.add(new Resource(WorkflowType.NETWORKCOLLECTION,
237                         serviceInstanceMSO.getCollection().getId(), false, serviceResource));
238             }
239             if (serviceInstanceMSO.getConfigurations() != null) {
240                 for (Configuration config : serviceInstanceMSO.getConfigurations()) {
241                     Optional<org.onap.aai.domain.yang.Configuration> aaiConfig =
242                             aaiConfigurationResources.getConfiguration(config.getConfigurationId());
243                     if (aaiConfig.isPresent() && aaiConfig.get().getRelationshipList() != null) {
244                         for (Relationship relationship : aaiConfig.get().getRelationshipList().getRelationship()) {
245                             if (relationship.getRelatedTo().contains("vnfc")
246                                     || relationship.getRelatedTo().contains("vpn-binding")) {
247                                 aaiResourceIds.add(new Pair<>(WorkflowType.CONFIGURATION, config.getConfigurationId()));
248                                 resourceList.add(new Resource(WorkflowType.CONFIGURATION, config.getConfigurationId(),
249                                         false, serviceResource));
250                                 break;
251                             }
252                         }
253                     }
254                 }
255             }
256         } catch (Exception ex) {
257             logger.error("Exception in traverseAAIService", ex);
258             buildAndThrowException(execution,
259                     "Could not find existing Service Instance or related Instances to execute the request on.");
260         }
261     }
262
263     private void traverseServiceInstanceMSOVnfs(List<Resource> resourceList, Resource serviceResource,
264             List<Pair<WorkflowType, String>> aaiResourceIds,
265             org.onap.so.bpmn.servicedecomposition.bbobjects.ServiceInstance serviceInstanceMSO) {
266         if (serviceInstanceMSO.getVnfs() == null) {
267             return;
268         }
269         for (org.onap.so.bpmn.servicedecomposition.bbobjects.GenericVnf vnf : serviceInstanceMSO.getVnfs()) {
270             aaiResourceIds.add(new Pair<>(WorkflowType.VNF, vnf.getVnfId()));
271             GenericVnf genericVnf = bbInputSetupUtils.getAAIGenericVnf(vnf.getVnfId());
272             Resource vnfResource = new Resource(WorkflowType.VNF, vnf.getVnfId(), false, serviceResource);
273             vnfResource.setVnfCustomizationId(genericVnf.getModelCustomizationId());
274             vnfResource.setModelCustomizationId(genericVnf.getModelCustomizationId());
275             vnfResource.setModelVersionId(genericVnf.getModelVersionId());
276             resourceList.add(vnfResource);
277             traverseVnfModules(resourceList, vnfResource, aaiResourceIds, vnf);
278             if (vnf.getVolumeGroups() != null) {
279                 for (org.onap.so.bpmn.servicedecomposition.bbobjects.VolumeGroup volumeGroup : vnf.getVolumeGroups()) {
280                     aaiResourceIds.add(new Pair<>(WorkflowType.VOLUMEGROUP, volumeGroup.getVolumeGroupId()));
281                     resourceList.add(
282                             new Resource(WorkflowType.VOLUMEGROUP, volumeGroup.getVolumeGroupId(), false, vnfResource));
283                 }
284             }
285         }
286     }
287
288     private void traverseServiceInstanceMSOPnfs(List<Resource> resourceList, Resource serviceResource,
289             List<Pair<WorkflowType, String>> aaiResourceIds,
290             org.onap.so.bpmn.servicedecomposition.bbobjects.ServiceInstance serviceInstanceMSO) {
291         if (serviceInstanceMSO.getPnfs() == null) {
292             return;
293         }
294         for (org.onap.so.bpmn.servicedecomposition.bbobjects.Pnf pnf : serviceInstanceMSO.getPnfs()) {
295             aaiResourceIds.add(new Pair<>(WorkflowType.PNF, pnf.getPnfId()));
296             Resource resource = new Resource(WorkflowType.PNF, pnf.getPnfId(), false, serviceResource);
297             ModelInfoPnf modelInfo = pnf.getModelInfoPnf();
298             if (modelInfo != null) {
299                 resource.setModelVersionId(modelInfo.getModelUuid());
300                 resource.setModelCustomizationId(modelInfo.getModelCustomizationUuid());
301             }
302             resourceList.add(resource);
303         }
304     }
305
306     public void traverseServiceInstanceChildService(List<Resource> resourceList, Resource serviceResource,
307             ServiceInstance serviceInstanceAAI) {
308
309         ComposedResources composedResources = serviceInstanceAAI.getComposedResources();
310         if (composedResources == null) {
311             return;
312         }
313
314         List<ComposedResource> listOfComposedResource = composedResources.getComposedResource();
315
316         listOfComposedResource.forEach(composedResource -> {
317             // Get ServiceInstance from composedResource relationship List
318             RelationshipList relationshipList = composedResource.getRelationshipList();
319             if (relationshipList == null) {
320                 return;
321             }
322             List<Relationship> composedResourceRelationshipList = relationshipList.getRelationship();
323             ServiceInstance childService = new ServiceInstance();
324             composedResourceRelationshipList.forEach(composedRelation -> {
325                 if ("service-instance".equalsIgnoreCase(composedRelation.getRelatedTo())) {
326                     List<RelationshipData> rData = composedRelation.getRelationshipData();
327                     rData.forEach(data -> {
328                         if ("service-instance.service-instance-id".equalsIgnoreCase(data.getRelationshipKey())) {
329                             childService.setServiceInstanceId(data.getRelationshipValue());
330                         }
331                     });
332                     composedRelation.getRelatedToProperty().forEach(relatedToProperty -> {
333                         if ("service-instance.service-instance-name"
334                                 .equalsIgnoreCase(relatedToProperty.getPropertyKey())) {
335                             childService.setServiceInstanceName(relatedToProperty.getPropertyValue());
336                         }
337                     });
338                 }
339             });
340
341             if (childService.getServiceInstanceId() == null) {
342                 return;
343             }
344
345             Resource childServiceResource =
346                     new Resource(WorkflowType.SERVICE, childService.getServiceInstanceId(), false, serviceResource);
347
348             childServiceResource.setInstanceName(childService.getServiceInstanceName());
349             resourceList.add(childServiceResource);
350         });
351
352     }
353
354     protected void traverseVrfConfiguration(List<Pair<WorkflowType, String>> aaiResourceIds,
355             List<Resource> resourceList, Resource serviceResource, org.onap.so.db.catalog.beans.Service service,
356             RelatedInstance relatedVpnBinding, RelatedInstance relatedLocalNetwork)
357             throws VrfBondingServiceException, JsonProcessingException {
358         org.onap.aai.domain.yang.L3Network aaiLocalNetwork =
359                 bbInputSetupUtils.getAAIL3Network(relatedLocalNetwork.getInstanceId());
360         vrfValidation.vrfServiceValidation(service);
361         vrfValidation.vrfCatalogDbChecks(service);
362         vrfValidation.aaiVpnBindingValidation(relatedVpnBinding.getInstanceId(),
363                 bbInputSetupUtils.getAAIVpnBinding(relatedVpnBinding.getInstanceId()));
364         vrfValidation.aaiNetworkValidation(relatedLocalNetwork.getInstanceId(), aaiLocalNetwork);
365         vrfValidation.aaiSubnetValidation(aaiLocalNetwork);
366         vrfValidation.aaiAggregateRouteValidation(aaiLocalNetwork);
367         vrfValidation.aaiRouteTargetValidation(aaiLocalNetwork);
368         String existingAAIVrfConfiguration = getExistingAAIVrfConfiguration(relatedVpnBinding, aaiLocalNetwork);
369         if (existingAAIVrfConfiguration != null) {
370             aaiResourceIds.add(new Pair<>(WorkflowType.CONFIGURATION, existingAAIVrfConfiguration));
371         }
372         resourceList.add(new Resource(WorkflowType.CONFIGURATION,
373                 service.getConfigurationCustomizations().get(0).getModelCustomizationUUID(), false, serviceResource));
374
375     }
376
377     protected void traverseNetworkCollection(DelegateExecution execution, List<Resource> resourceList,
378             Resource serviceResource, org.onap.so.db.catalog.beans.Service service) {
379         if (isVnfCustomizationsInTheService(service)) {
380             buildAndThrowException(execution,
381                     "Cannot orchestrate Service-Macro-Create without user params with a vnf. Please update ASDC model for new macro orchestration support or add service_recipe records to route to old macro flows");
382         }
383         if (isPnfCustomizationsInTheService(service)) {
384             buildAndThrowException(execution,
385                     "Cannot orchestrate Service-Macro-Create without user params with a pnf. Please update ASDC model for new macro orchestration support or add service_recipe records to route to old macro flows");
386         }
387         List<CollectionResourceCustomization> customizations = service.getCollectionResourceCustomizations();
388         if (customizations.isEmpty()) {
389             logger.debug("No Collections found. CollectionResourceCustomization list is empty.");
390         } else {
391             CollectionResourceCustomization collectionResourceCustomization =
392                     findCatalogNetworkCollection(execution, service);
393             traverseNetworkCollectionResourceCustomization(resourceList, serviceResource,
394                     collectionResourceCustomization);
395         }
396         traverseNetworkCollectionCustomization(resourceList, serviceResource, service);
397     }
398
399     private void traverseNetworkCollectionResourceCustomization(List<Resource> resourceList, Resource serviceResource,
400             CollectionResourceCustomization collectionResourceCustomization) {
401         if (collectionResourceCustomizationShouldNotBeProcessed(resourceList, serviceResource,
402                 collectionResourceCustomization))
403             return;
404         int minNetworks = 0;
405         org.onap.so.db.catalog.beans.InstanceGroup instanceGroup =
406                 collectionResourceCustomization.getCollectionResource().getInstanceGroup();
407         CollectionResourceInstanceGroupCustomization collectionInstCust = null;
408         if (!instanceGroup.getCollectionInstanceGroupCustomizations().isEmpty()) {
409             for (CollectionResourceInstanceGroupCustomization collectionInstanceGroupTemp : instanceGroup
410                     .getCollectionInstanceGroupCustomizations()) {
411                 if (collectionInstanceGroupTemp.getModelCustomizationUUID()
412                         .equalsIgnoreCase(collectionResourceCustomization.getModelCustomizationUUID())) {
413                     collectionInstCust = collectionInstanceGroupTemp;
414                     break;
415                 }
416             }
417             if (interfaceNetworkQuantityIsAvailableInCollection(collectionInstCust)) {
418                 minNetworks = collectionInstCust.getSubInterfaceNetworkQuantity();
419             }
420         }
421         logger.debug("minNetworks: {}", minNetworks);
422         CollectionNetworkResourceCustomization collectionNetworkResourceCust =
423                 getCollectionNetworkResourceCustomization(collectionResourceCustomization, instanceGroup);
424         for (int i = 0; i < minNetworks; i++) {
425             if (collectionNetworkResourceCust != null) {
426                 Resource resource = new Resource(WorkflowType.VIRTUAL_LINK,
427                         collectionNetworkResourceCust.getModelCustomizationUUID(), false, serviceResource);
428                 resource.setVirtualLinkKey(Integer.toString(i));
429                 resourceList.add(resource);
430             }
431         }
432     }
433
434     private CollectionNetworkResourceCustomization getCollectionNetworkResourceCustomization(
435             CollectionResourceCustomization collectionResourceCustomization, InstanceGroup instanceGroup) {
436         CollectionNetworkResourceCustomization collectionNetworkResourceCust = null;
437         for (CollectionNetworkResourceCustomization collectionNetworkTemp : instanceGroup
438                 .getCollectionNetworkResourceCustomizations()) {
439             if (collectionNetworkTemp.getNetworkResourceCustomization().getModelCustomizationUUID()
440                     .equalsIgnoreCase(collectionResourceCustomization.getModelCustomizationUUID())) {
441                 collectionNetworkResourceCust = collectionNetworkTemp;
442                 break;
443             }
444         }
445         return collectionNetworkResourceCust;
446     }
447
448     private boolean collectionResourceCustomizationShouldNotBeProcessed(List<Resource> resourceList,
449             Resource serviceResource, CollectionResourceCustomization collectionResourceCustomization) {
450         if (collectionResourceCustomization == null) {
451             logger.debug("No Network Collection Customization found");
452             return true;
453         }
454         resourceList.add(new Resource(WorkflowType.NETWORKCOLLECTION,
455                 collectionResourceCustomization.getModelCustomizationUUID(), false, serviceResource));
456         logger.debug("Found a network collection");
457         if (collectionResourceCustomization.getCollectionResource() == null) {
458             logger.debug("No Network Collection found. collectionResource is null");
459             return true;
460         }
461         if (collectionResourceCustomization.getCollectionResource().getInstanceGroup() == null) {
462             logger.debug("No Instance Group found for network collection.");
463             return true;
464         }
465         String toscaNodeType =
466                 collectionResourceCustomization.getCollectionResource().getInstanceGroup().getToscaNodeType();
467         if (!toscaNodeTypeHasNetworkCollection(toscaNodeType)) {
468             logger.debug("Instance Group tosca node type does not contain NetworkCollection:  {}", toscaNodeType);
469             return true;
470         }
471         return false;
472     }
473
474     private boolean interfaceNetworkQuantityIsAvailableInCollection(
475             CollectionResourceInstanceGroupCustomization collectionInstCust) {
476         return collectionInstCust != null && collectionInstCust.getSubInterfaceNetworkQuantity() != null;
477     }
478
479     private boolean toscaNodeTypeHasNetworkCollection(String toscaNodeType) {
480         return toscaNodeType != null && toscaNodeType.contains(NETWORKCOLLECTION);
481     }
482
483     private void traverseNetworkCollectionCustomization(List<Resource> resourceList, Resource serviceResource,
484             org.onap.so.db.catalog.beans.Service service) {
485         if (isNetworkCollectionInTheResourceList(resourceList)) {
486             return;
487         }
488         if (service.getNetworkCustomizations() == null) {
489             logger.debug("No networks were found on this service model");
490             return;
491         }
492         for (int i = 0; i < service.getNetworkCustomizations().size(); i++) {
493             resourceList.add(new Resource(WorkflowType.NETWORK,
494                     service.getNetworkCustomizations().get(i).getModelCustomizationUUID(), false, serviceResource));
495         }
496     }
497
498     private boolean isVnfCustomizationsInTheService(org.onap.so.db.catalog.beans.Service service) {
499         return !(service.getVnfCustomizations() == null || service.getVnfCustomizations().isEmpty());
500     }
501
502     private boolean isPnfCustomizationsInTheService(org.onap.so.db.catalog.beans.Service service) {
503         return !(service.getPnfCustomizations() == null || service.getPnfCustomizations().isEmpty());
504     }
505
506     private void traverseVnfModules(List<Resource> resourceList, Resource vnfResource,
507             List<Pair<WorkflowType, String>> aaiResourceIds,
508             org.onap.so.bpmn.servicedecomposition.bbobjects.GenericVnf vnf) {
509         if (vnf.getVfModules() == null) {
510             return;
511         }
512         for (VfModule vfModule : vnf.getVfModules()) {
513             aaiResourceIds.add(new Pair<>(WorkflowType.VFMODULE, vfModule.getVfModuleId()));
514             Resource resource = new Resource(WorkflowType.VFMODULE, vfModule.getVfModuleId(), false, vnfResource);
515             org.onap.aai.domain.yang.VfModule aaiVfModule =
516                     bbInputSetupUtils.getAAIVfModule(vnf.getVnfId(), vfModule.getVfModuleId());
517             resource.setModelCustomizationId(aaiVfModule.getModelCustomizationId());
518             resource.setModelInvariantId(aaiVfModule.getModelInvariantId());
519             resource.setBaseVfModule(vfModule.getModelInfoVfModule().getIsBaseBoolean());
520             resourceList.add(resource);
521         }
522     }
523
524
525     protected String getExistingAAIVrfConfiguration(RelatedInstance relatedVpnBinding,
526             org.onap.aai.domain.yang.L3Network aaiLocalNetwork)
527             throws JsonProcessingException, VrfBondingServiceException {
528         Optional<Relationships> relationshipsOp = new AAIResultWrapper(
529                 new AAICommonObjectMapperProvider().getMapper().writeValueAsString(aaiLocalNetwork)).getRelationships();
530         if (relationshipsOp.isPresent()) {
531             List<AAIResultWrapper> configurationsRelatedToLocalNetwork =
532                     relationshipsOp.get().getByType(AAIFluentTypeBuilder.Types.CONFIGURATION);
533             if (configurationsRelatedToLocalNetwork.size() > 1) {
534                 throw new VrfBondingServiceException(
535                         "Network: " + aaiLocalNetwork.getNetworkId() + " has more than 1 configuration related to it");
536             }
537             if (configurationsRelatedToLocalNetwork.size() == 1) {
538                 AAIResultWrapper configWrapper = configurationsRelatedToLocalNetwork.get(0);
539                 Optional<Configuration> relatedConfiguration = configWrapper.asBean(Configuration.class);
540                 if (relatedConfiguration.isPresent() && vrfConfigurationAlreadyExists(relatedVpnBinding,
541                         relatedConfiguration.get(), configWrapper)) {
542                     return relatedConfiguration.get().getConfigurationId();
543                 }
544             }
545         }
546         return null;
547     }
548
549     protected boolean vrfConfigurationAlreadyExists(RelatedInstance relatedVpnBinding, Configuration vrfConfiguration,
550             AAIResultWrapper configWrapper) throws VrfBondingServiceException {
551         if ("VRF-ENTRY".equalsIgnoreCase(vrfConfiguration.getConfigurationType())) {
552             Optional<Relationships> relationshipsConfigOp = configWrapper.getRelationships();
553             if (relationshipsConfigOp.isPresent()) {
554                 Optional<VpnBinding> relatedInfraVpnBindingOp =
555                         workflowActionUtils.extractRelationshipsVpnBinding(relationshipsConfigOp.get());
556                 if (relatedInfraVpnBindingOp.isPresent()) {
557                     VpnBinding relatedInfraVpnBinding = relatedInfraVpnBindingOp.get();
558                     if (!relatedInfraVpnBinding.getVpnId().equalsIgnoreCase(relatedVpnBinding.getInstanceId())) {
559                         throw new VrfBondingServiceException("Configuration: " + vrfConfiguration.getConfigurationId()
560                                 + " is not connected to the same vpn binding id provided in request: "
561                                 + relatedVpnBinding.getInstanceId());
562                     } else {
563                         return true;
564                     }
565                 }
566             }
567         }
568         return false;
569     }
570
571     public boolean containsWorkflowType(List<Resource> resourceList, WorkflowType workflowType) {
572         return resourceList.stream().anyMatch(resource -> resource.getResourceType().equals(workflowType));
573     }
574
575     public boolean isNetworkCollectionInTheResourceList(List<Resource> resourceList) {
576         return resourceList.stream().anyMatch(x -> WorkflowType.NETWORKCOLLECTION == x.getResourceType());
577     }
578
579     public CollectionResourceCustomization findCatalogNetworkCollection(DelegateExecution execution,
580             org.onap.so.db.catalog.beans.Service service) {
581         CollectionResourceCustomization networkCollection = null;
582         int count = 0;
583         for (CollectionResourceCustomization collectionCust : service.getCollectionResourceCustomizations()) {
584             if (catalogDbClient.getNetworkCollectionResourceCustomizationByID(
585                     collectionCust.getModelCustomizationUUID()) != null) {
586                 networkCollection = collectionCust;
587                 count++;
588             }
589         }
590         if (count == 0) {
591             return null;
592         } else if (count > 1) {
593             buildAndThrowException(execution,
594                     "Found multiple Network Collections in the Service model, only one per Service is supported.");
595         }
596         return networkCollection;
597     }
598
599     protected void buildAndThrowException(DelegateExecution execution, String msg) {
600         logger.error(msg);
601         execution.setVariable(WORKFLOW_ACTION_ERROR_MESSAGE, msg);
602         exceptionBuilder.buildAndThrowWorkflowException(execution, 7000, msg);
603     }
604 }