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