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