Merge "provide correct custIds"
[so.git] / bpmn / so-bpmn-tasks / src / main / java / org / onap / so / bpmn / infrastructure / aai / tasks / AAICreateTasks.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP - SO
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.so.bpmn.infrastructure.aai.tasks;
22
23 import java.util.Arrays;
24 import java.util.List;
25 import java.util.Optional;
26 import java.util.TreeSet;
27 import java.util.UUID;
28 import java.util.stream.Collectors;
29
30 import org.camunda.bpm.engine.delegate.BpmnError;
31 import org.onap.so.bpmn.common.BuildingBlockExecution;
32 import org.onap.so.bpmn.servicedecomposition.bbobjects.CloudRegion;
33 import org.onap.so.bpmn.servicedecomposition.bbobjects.Collection;
34 import org.onap.so.bpmn.servicedecomposition.bbobjects.Configuration;
35 import org.onap.so.bpmn.servicedecomposition.bbobjects.Customer;
36 import org.onap.so.bpmn.servicedecomposition.bbobjects.GenericVnf;
37 import org.onap.so.bpmn.servicedecomposition.bbobjects.InstanceGroup;
38 import org.onap.so.bpmn.servicedecomposition.bbobjects.L3Network;
39 import org.onap.so.bpmn.servicedecomposition.bbobjects.LineOfBusiness;
40 import org.onap.so.bpmn.servicedecomposition.bbobjects.NetworkPolicy;
41 import org.onap.so.bpmn.servicedecomposition.bbobjects.OwningEntity;
42 import org.onap.so.bpmn.servicedecomposition.bbobjects.Platform;
43 import org.onap.so.bpmn.servicedecomposition.bbobjects.Project;
44 import org.onap.so.bpmn.servicedecomposition.bbobjects.ServiceInstance;
45 import org.onap.so.bpmn.servicedecomposition.bbobjects.VfModule;
46 import org.onap.so.bpmn.servicedecomposition.bbobjects.VolumeGroup;
47 import org.onap.so.bpmn.servicedecomposition.entities.GeneralBuildingBlock;
48 import org.onap.so.bpmn.servicedecomposition.entities.ResourceKey;
49 import org.onap.so.bpmn.servicedecomposition.tasks.ExtractPojosForBB;
50 import org.onap.so.client.aai.AAIObjectPlurals;
51 import org.onap.so.client.aai.entities.uri.AAIResourceUri;
52 import org.onap.so.client.aai.entities.uri.AAIUriFactory;
53 import org.onap.so.client.exception.BBObjectNotFoundException;
54 import org.onap.so.client.exception.ExceptionBuilder;
55 import org.onap.so.client.orchestration.AAIConfigurationResources;
56 import org.onap.so.client.orchestration.AAINetworkResources;
57 import org.onap.so.client.orchestration.AAIServiceInstanceResources;
58 import org.onap.so.client.orchestration.AAIVfModuleResources;
59 import org.onap.so.client.orchestration.AAIVnfResources;
60 import org.onap.so.client.orchestration.AAIVolumeGroupResources;
61 import org.onap.so.client.orchestration.AAIVpnBindingResources;
62 import org.onap.so.logger.MessageEnum;
63 import org.onap.so.logger.MsoLogger;
64 import org.slf4j.Logger;
65 import org.slf4j.LoggerFactory;
66 import org.springframework.beans.factory.annotation.Autowired;
67 import org.springframework.core.env.Environment;
68 import org.springframework.stereotype.Component;
69
70 @Component
71 public class AAICreateTasks {
72
73         private static final MsoLogger msoLogger = MsoLogger.getMsoLogger(MsoLogger.Catalog.BPEL, AAICreateTasks.class);
74         private static final Logger logger = LoggerFactory.getLogger(AAICreateTasks.class.getName());
75         
76         private static final String networkTypeProvider = "PROVIDER";
77         private static String NETWORK_COLLECTION_NAME = "networkCollectionName";
78         private static String CONTRAIL_NETWORK_POLICY_FQDN_LIST = "contrailNetworkPolicyFqdnList";
79         private static String HEAT_STACK_ID = "heatStackId";
80         private static String NETWORK_POLICY_FQDN_PARAM = "network-policy-fqdn";
81         @Autowired
82         private AAIServiceInstanceResources aaiSIResources;
83         @Autowired
84         private AAIVnfResources aaiVnfResources;
85         @Autowired
86         private ExceptionBuilder exceptionUtil;
87         @Autowired
88         private ExtractPojosForBB extractPojosForBB;
89         @Autowired
90         private AAIVolumeGroupResources aaiVolumeGroupResources;
91         @Autowired
92         private AAIVfModuleResources aaiVfModuleResources;
93         @Autowired
94         private AAINetworkResources aaiNetworkResources;
95         @Autowired
96         private AAIVpnBindingResources aaiVpnBindingResources;
97         @Autowired
98         private AAIConfigurationResources aaiConfigurationResources;
99         @Autowired
100         private Environment env;
101
102         public void createServiceInstance(BuildingBlockExecution execution) {
103                 try {
104                         ServiceInstance serviceInstance = extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID, execution.getLookupMap().get(ResourceKey.SERVICE_INSTANCE_ID));
105                         Customer customer = execution.getGeneralBuildingBlock().getCustomer();
106                         aaiSIResources.createServiceInstance(serviceInstance, customer);
107                 } catch (Exception ex) {
108                         exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
109                 }
110         }
111
112     public void createServiceSubscription(BuildingBlockExecution execution){
113         try{
114             ServiceInstance serviceInstance = extractPojosForBB.extractByKey(execution,
115                     ResourceKey.SERVICE_INSTANCE_ID, execution.getLookupMap().get(ResourceKey.SERVICE_INSTANCE_ID));
116             Customer customer = execution.getGeneralBuildingBlock().getCustomer();
117             if (null == customer) {
118                 String errorMessage = "Exception in creating ServiceSubscription. Customer not present for ServiceInstanceID: "
119                         + serviceInstance.getServiceInstanceId();
120                 msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, errorMessage, "BPMN", MsoLogger.getServiceName(),
121                         MsoLogger.ErrorCode.UnknownError, errorMessage);
122                 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, errorMessage);
123             }
124             aaiSIResources.createServiceSubscription(customer);
125         } catch (BpmnError ex) {
126             throw ex;
127         }
128         catch (Exception ex) {
129             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
130         }
131     }
132
133         public void createProject(BuildingBlockExecution execution) {
134                 try {
135                         ServiceInstance serviceInstance = extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID, execution.getLookupMap().get(ResourceKey.SERVICE_INSTANCE_ID));
136                         Project project = serviceInstance.getProject();
137                         if(project != null) {
138                                 if (project.getProjectName() == null || "".equals(project.getProjectName())) {
139                                         msoLogger.info("ProjectName is null in input. Skipping create project...");
140                                 } else {
141                                         aaiSIResources.createProjectandConnectServiceInstance(project, serviceInstance);
142                                 }
143                         }
144                 } catch (Exception ex) {
145                         exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
146                 }
147         }
148
149         public void createOwningEntity(BuildingBlockExecution execution) {
150                 try {
151                         ServiceInstance serviceInstance = extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID, execution.getLookupMap().get(ResourceKey.SERVICE_INSTANCE_ID));
152                         OwningEntity owningEntity = serviceInstance.getOwningEntity();
153                         String owningEntityId = owningEntity.getOwningEntityId();
154                         String owningEntityName = owningEntity.getOwningEntityName();
155                         if (owningEntityId == null || "".equals(owningEntityId)) {
156                                 String msg = "Exception in AAICreateOwningEntity. OwningEntityId is null.";
157                                 execution.setVariable("ErrorCreateOEAAI", msg);
158                                 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg);
159                         } else {
160                                 if (aaiSIResources.existsOwningEntity(owningEntity)) {
161                                         aaiSIResources.connectOwningEntityandServiceInstance(owningEntity, serviceInstance);
162                                 } else {
163                                         if (owningEntityName == null || "".equals(owningEntityName)) {
164                                                 String msg = "Exception in AAICreateOwningEntity. Can't create an owningEntity with no owningEntityName.";
165                                                 msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, msg, "BPMN", MsoLogger.getServiceName(),
166                                                                 MsoLogger.ErrorCode.UnknownError, msg);
167                                                 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg);
168                                         } else {
169                                                 if(aaiSIResources.existsOwningEntityName(owningEntityName)){
170                                                         String msg = "Exception in AAICreateOwningEntity. Can't create OwningEntity as name already exists in AAI associated with a different owning-entity-id (name must be unique)";
171                                                         msoLogger.error(MessageEnum.BPMN_GENERAL_EXCEPTION_ARG, msg, "BPMN", MsoLogger.getServiceName(),
172                                                                         MsoLogger.ErrorCode.UnknownError, msg);
173                                                         exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg);
174                                                 }else{
175                                                         aaiSIResources.createOwningEntityandConnectServiceInstance(owningEntity, serviceInstance);
176                                                 }
177                                         }
178                                 }
179                         }
180                 } catch (Exception ex) {
181                         exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
182                 }
183         }
184
185         public void createVnf(BuildingBlockExecution execution) {
186                 try {
187                         GenericVnf vnf = extractPojosForBB.extractByKey(execution, ResourceKey.GENERIC_VNF_ID, execution.getLookupMap().get(ResourceKey.GENERIC_VNF_ID));
188                         ServiceInstance serviceInstance = extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID, execution.getLookupMap().get(ResourceKey.SERVICE_INSTANCE_ID));
189                         execution.setVariable("callHoming", Boolean.TRUE.equals(vnf.isCallHoming()));
190                         aaiVnfResources.createVnfandConnectServiceInstance(vnf, serviceInstance);
191                 } catch (Exception ex) {
192                         exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
193                 }
194         }
195         
196         public void createPlatform(BuildingBlockExecution execution) {
197                 try {
198                         GenericVnf vnf = extractPojosForBB.extractByKey(execution, ResourceKey.GENERIC_VNF_ID, execution.getLookupMap().get(ResourceKey.GENERIC_VNF_ID));
199                         Platform platform = vnf.getPlatform();
200                         if(platform != null) {
201                                 if (platform.getPlatformName() == null || "".equals(platform.getPlatformName())) {
202                                         msoLogger.debug("PlatformName is null in input. Skipping create platform...");
203                                 } else {
204                                         aaiVnfResources.createPlatformandConnectVnf(platform,vnf);
205                                 }
206                         }
207                 } catch (Exception ex) {
208                         exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
209                 }
210
211         }
212         
213         public void createLineOfBusiness(BuildingBlockExecution execution) {
214                 try {
215                         GenericVnf vnf = extractPojosForBB.extractByKey(execution, ResourceKey.GENERIC_VNF_ID, execution.getLookupMap().get(ResourceKey.GENERIC_VNF_ID));
216                         LineOfBusiness lineOfBusiness = vnf.getLineOfBusiness();
217                         if(lineOfBusiness != null) {
218                                 if (lineOfBusiness.getLineOfBusinessName() == null || "".equals(lineOfBusiness.getLineOfBusinessName())) {
219                                         msoLogger.info("lineOfBusiness is null in input. Skipping create lineOfBusiness...");
220                                 } else {
221                                         aaiVnfResources.createLineOfBusinessandConnectVnf(lineOfBusiness,vnf);
222                                 }
223                         }
224                 } catch (Exception ex) {
225                         exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
226                 }
227         }
228
229         public void createVolumeGroup(BuildingBlockExecution execution) {
230                 try {
231                         GeneralBuildingBlock gBBInput = execution.getGeneralBuildingBlock();
232                         
233                         GenericVnf genericVnf = extractPojosForBB.extractByKey(execution, ResourceKey.GENERIC_VNF_ID, execution.getLookupMap().get(ResourceKey.GENERIC_VNF_ID));
234                         VolumeGroup volumeGroup = extractPojosForBB.extractByKey(execution, ResourceKey.VOLUME_GROUP_ID, execution.getLookupMap().get(ResourceKey.VOLUME_GROUP_ID));
235                         CloudRegion cloudRegion = gBBInput.getCloudRegion();
236                         aaiVolumeGroupResources.createVolumeGroup(volumeGroup, cloudRegion);
237                         aaiVolumeGroupResources.connectVolumeGroupToVnf(genericVnf, volumeGroup, cloudRegion);
238                         aaiVolumeGroupResources.connectVolumeGroupToTenant(volumeGroup,cloudRegion);
239                 } catch (Exception ex) {
240                         exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
241                 }
242         }
243         
244         public void createVfModule(BuildingBlockExecution execution) {
245                 try {
246                         GenericVnf vnf = extractPojosForBB.extractByKey(execution, ResourceKey.GENERIC_VNF_ID, execution.getLookupMap().get(ResourceKey.GENERIC_VNF_ID));
247                         VfModule vfModule = extractPojosForBB.extractByKey(execution, ResourceKey.VF_MODULE_ID, execution.getLookupMap().get(ResourceKey.VF_MODULE_ID));
248                         int moduleIndex = 0;
249                         if (vfModule.getModelInfoVfModule() != null && !Boolean.TRUE.equals(vfModule.getModelInfoVfModule().getIsBaseBoolean())) {
250                                 moduleIndex = this.getLowestUnusedVfModuleIndexFromAAIVnfResponse(vnf, vfModule);
251                         }
252                         vfModule.setModuleIndex(moduleIndex);
253                         aaiVfModuleResources.createVfModule(vfModule, vnf);
254                 } catch (Exception ex) {                        
255                         exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
256                 }       
257         }
258         
259         /**
260          * BPMN access method to establish relationships in AAI
261          * @param execution
262          * @throws Exception
263          */
264         public void connectVfModuleToVolumeGroup(BuildingBlockExecution execution) {
265                 try {
266                         GenericVnf vnf = extractPojosForBB.extractByKey(execution, ResourceKey.GENERIC_VNF_ID, execution.getLookupMap().get(ResourceKey.GENERIC_VNF_ID));
267                         VfModule vfModule = extractPojosForBB.extractByKey(execution, ResourceKey.VF_MODULE_ID, execution.getLookupMap().get(ResourceKey.VF_MODULE_ID));
268                         VolumeGroup volumeGroup = null;
269                         try{
270                                 volumeGroup = extractPojosForBB.extractByKey(execution, ResourceKey.VOLUME_GROUP_ID, execution.getLookupMap().get(ResourceKey.VOLUME_GROUP_ID));
271                         } catch (BBObjectNotFoundException e){
272                                 msoLogger.info("VolumeGroup not found. Skipping Connect between VfModule and VolumeGroup");
273                         }
274                         if (volumeGroup != null) {
275                                 aaiVfModuleResources.connectVfModuleToVolumeGroup(vnf, vfModule, volumeGroup, execution.getGeneralBuildingBlock().getCloudRegion());
276                         }
277                 } catch (Exception ex) {
278                         exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
279                 }       
280         }
281         
282         /**
283          * BPMN access method to execute Create L3Network operation (PUT )in AAI
284          * @param execution
285          * @throws Exception
286          */
287         public void createNetwork(BuildingBlockExecution execution) {
288                 try {
289                         ServiceInstance serviceInstance = extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID, execution.getLookupMap().get(ResourceKey.SERVICE_INSTANCE_ID));
290                         L3Network l3network =  extractPojosForBB.extractByKey(execution, ResourceKey.NETWORK_ID, execution.getLookupMap().get(ResourceKey.NETWORK_ID));
291                         //set default to false. ToBe updated by SDNC
292                         l3network.setIsBoundToVpn(false);
293                         //define is bound to vpn flag as true if NEUTRON_NETWORK_TYPE is PROVIDER
294                         if (l3network.getModelInfoNetwork().getNeutronNetworkType().equalsIgnoreCase(networkTypeProvider))
295                                 l3network.setIsBoundToVpn(true);
296                         //put network shell in AAI
297                         aaiNetworkResources.createNetworkConnectToServiceInstance(l3network, serviceInstance);
298                 } catch (Exception ex) {
299                         exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
300                 }       
301         }
302         public void createCustomer(BuildingBlockExecution execution) throws Exception {
303                 try {
304                         Customer customer = execution.getGeneralBuildingBlock().getCustomer();
305                         
306                         aaiVpnBindingResources.createCustomer(customer);
307                 } catch(Exception ex) {
308                         exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
309                 }
310         }
311         
312         /**
313          * BPMN access method to execute NetworkCollection operation (PUT) in AAI
314          * @param execution
315          * @throws Exception
316          */
317         public void createNetworkCollection(BuildingBlockExecution execution) {
318                 try {
319                         ServiceInstance serviceInstance = extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID, execution.getLookupMap().get(ResourceKey.SERVICE_INSTANCE_ID));
320                         Collection networkCollection =  serviceInstance.getCollection();
321                         //pass name generated for NetworkCollection/NetworkCollectionInstanceGroup in previous step of the BB flow
322                         //put shell in AAI
323                         networkCollection.setName(execution.getVariable(NETWORK_COLLECTION_NAME));
324                         aaiNetworkResources.createNetworkCollection(networkCollection);
325                 } catch (Exception ex) {
326                         exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
327                 }       
328         }
329         
330         /**
331          * BPMN access method to execute NetworkCollectionInstanceGroup operation (PUT) in AAI
332          * @param execution
333          * @throws Exception
334          */
335         public void createNetworkCollectionInstanceGroup(BuildingBlockExecution execution) {
336                 try {
337                         ServiceInstance serviceInstance = extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID, execution.getLookupMap().get(ResourceKey.SERVICE_INSTANCE_ID));
338                         InstanceGroup instanceGroup =  serviceInstance.getCollection().getInstanceGroup();
339                         //set name generated for NetworkCollection/NetworkCollectionInstanceGroup in previous step of the BB flow
340                         instanceGroup.setInstanceGroupName(execution.getVariable(NETWORK_COLLECTION_NAME));
341                         //put shell in AAI
342                         aaiNetworkResources.createNetworkInstanceGroup(instanceGroup);
343                 } catch (Exception ex) {
344                         exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
345                 }       
346         }
347         
348         
349         /**
350          * BPMN access method to establish relationships in AAI
351          * @param execution
352          * @throws Exception
353          */
354         public void connectNetworkToTenant(BuildingBlockExecution execution) {
355                 try {
356                         L3Network l3network =  extractPojosForBB.extractByKey(execution, ResourceKey.NETWORK_ID, execution.getLookupMap().get(ResourceKey.NETWORK_ID));
357                         aaiNetworkResources.connectNetworkToTenant(l3network, execution.getGeneralBuildingBlock().getCloudRegion());
358                 } catch (Exception ex) {
359                         exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
360                 }       
361         }
362         
363         /**
364          * BPMN access method to establish relationships in AAI
365          * @param execution
366          * @throws Exception
367          */
368         public void connectNetworkToCloudRegion(BuildingBlockExecution execution) {
369                 try {
370                         L3Network l3network =  extractPojosForBB.extractByKey(execution, ResourceKey.NETWORK_ID, execution.getLookupMap().get(ResourceKey.NETWORK_ID));
371                         aaiNetworkResources.connectNetworkToCloudRegion(l3network, execution.getGeneralBuildingBlock().getCloudRegion());
372                 } catch (Exception ex) {
373                         exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
374                 }       
375         }
376         
377         /**
378          * BPMN access method to establish relationships in AAI
379          * @param execution
380          * @throws Exception
381          */
382         public void connectVnfToCloudRegion(BuildingBlockExecution execution) {
383                 try {
384                         boolean cloudRegionsToSkip = false;
385                         String[] cloudRegions = env.getProperty("mso.bpmn.cloudRegionIdsToSkipAddingVnfEdgesTo", String[].class);
386                         if (cloudRegions != null){
387                                 cloudRegionsToSkip = Arrays.stream(cloudRegions).anyMatch(execution.getGeneralBuildingBlock().getCloudRegion().getLcpCloudRegionId()::equals);
388                         }
389                         if(!cloudRegionsToSkip) {
390                                 GenericVnf vnf = extractPojosForBB.extractByKey(execution, ResourceKey.GENERIC_VNF_ID, execution.getLookupMap().get(ResourceKey.GENERIC_VNF_ID));
391                                 aaiVnfResources.connectVnfToCloudRegion(vnf, execution.getGeneralBuildingBlock().getCloudRegion());
392                         }
393                 } catch (Exception ex) {
394                         exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
395                 }       
396         }
397         
398         /**
399          * BPMN access method to establish relationships in AAI
400          * @param execution
401          * @throws Exception
402          */
403         public void connectVnfToTenant(BuildingBlockExecution execution) {
404                 try {
405                         GenericVnf vnf = extractPojosForBB.extractByKey(execution, ResourceKey.GENERIC_VNF_ID, execution.getLookupMap().get(ResourceKey.GENERIC_VNF_ID));
406                         aaiVnfResources.connectVnfToTenant(vnf, execution.getGeneralBuildingBlock().getCloudRegion());
407                 } catch (Exception ex) {
408                         exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
409                 }       
410         }
411         
412         /**
413          * BPMN access method to establish relationships in AAI
414          * @param execution
415          * @throws Exception
416          */
417         public void connectNetworkToNetworkCollectionServiceInstance(BuildingBlockExecution execution) {
418                 try {
419                         ServiceInstance serviceInstance = extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID, execution.getLookupMap().get(ResourceKey.SERVICE_INSTANCE_ID));
420                         L3Network l3network =  extractPojosForBB.extractByKey(execution, ResourceKey.NETWORK_ID, execution.getLookupMap().get(ResourceKey.NETWORK_ID));
421                         aaiNetworkResources.connectNetworkToNetworkCollectionServiceInstance(l3network, serviceInstance);
422                 } catch (Exception ex) {
423                         exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
424                 }       
425         }
426         
427         /**
428          * BPMN access method to establish relationships in AAI
429          * @param execution
430          * @throws Exception
431          */
432         public void connectNetworkToNetworkCollectionInstanceGroup(BuildingBlockExecution execution) {
433                 try {
434                         ServiceInstance serviceInstance = extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID, execution.getLookupMap().get(ResourceKey.SERVICE_INSTANCE_ID));
435                         L3Network l3network =  extractPojosForBB.extractByKey(execution, ResourceKey.NETWORK_ID, execution.getLookupMap().get(ResourceKey.NETWORK_ID));
436                         //connect network only if Instance Group / Collection objects exist
437                         if (serviceInstance.getCollection() != null && serviceInstance.getCollection().getInstanceGroup() != null)
438                                 aaiNetworkResources.connectNetworkToNetworkCollectionInstanceGroup(l3network, serviceInstance.getCollection().getInstanceGroup());
439                 } catch (Exception ex) {
440                         exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
441                 }       
442         }
443         
444         public void createConfiguration(BuildingBlockExecution execution){
445                 try{
446                         Configuration configuration = extractPojosForBB.extractByKey(execution, ResourceKey.CONFIGURATION_ID, execution.getLookupMap().get(ResourceKey.CONFIGURATION_ID));
447                         aaiConfigurationResources.createConfiguration(configuration);
448                 } catch (Exception ex) {
449                         exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
450                 }
451         }
452         
453         public void createNetworkPolicies(BuildingBlockExecution execution) {
454                 try{                    
455                         String fqdns = execution.getVariable(CONTRAIL_NETWORK_POLICY_FQDN_LIST);
456                         if (fqdns != null && !fqdns.isEmpty()) {
457                                 String fqdnList[] = fqdns.split(",");
458                                 int fqdnCount = fqdnList.length;
459                                 if (fqdnCount > 0) {
460                                         for (int i=0; i < fqdnCount; i++) {
461                                                 String fqdn = fqdnList[i];
462                                                 AAIResourceUri uri = AAIUriFactory.createResourceUri(AAIObjectPlurals.NETWORK_POLICY);
463                                                 uri.queryParam(NETWORK_POLICY_FQDN_PARAM, fqdn);
464                                                 Optional<org.onap.aai.domain.yang.NetworkPolicy> oNetPolicy = aaiNetworkResources.getNetworkPolicy(uri);
465                                                 if(!oNetPolicy.isPresent()) {                                                           
466                                                         msoLogger.debug("This network policy FQDN is not in AAI yet: " + fqdn);                                                                 
467                                                         String networkPolicyId = UUID.randomUUID().toString();
468                                                         msoLogger.debug("Adding network-policy with network-policy-id " + networkPolicyId);
469                                                         NetworkPolicy networkPolicy = new NetworkPolicy();
470                                                         networkPolicy.setNetworkPolicyId(networkPolicyId);
471                                                         networkPolicy.setNetworkPolicyFqdn(fqdn);
472                                                         networkPolicy.setHeatStackId(execution.getVariable(HEAT_STACK_ID));
473                                                                         
474                                                         aaiNetworkResources.createNetworkPolicy(networkPolicy);
475                                                 }
476                                         }
477                                 }
478                         }                       
479                 } catch (Exception ex) {
480                         exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
481                 }               
482         }
483         
484         /**
485          * Groups existing vf modules by the model uuid of our new vf module and returns the lowest unused index
486          * 
487          * if we have a module type A, and there are 3 instances of those, 
488          * and then module type B has 2 instances, if we are adding a new module type A, 
489          * the vf-module-index should be 3 assuming contiguous indices (not 5, or 2)
490          * 
491          */
492         protected int getLowestUnusedVfModuleIndexFromAAIVnfResponse(GenericVnf genericVnf, VfModule newVfModule) {
493                 
494                 String newVfModuleModelInvariantUUID = null;
495                 if (newVfModule.getModelInfoVfModule() != null) {
496                         newVfModuleModelInvariantUUID = newVfModule.getModelInfoVfModule().getModelInvariantUUID();
497                 }
498                 
499                 
500                 if (genericVnf != null && genericVnf.getVfModules() != null && !genericVnf.getVfModules().isEmpty()) {
501                         List<VfModule> modules = genericVnf.getVfModules().stream().filter(item -> !item.getVfModuleId().equals(newVfModule.getVfModuleId())).collect(Collectors.toList());
502                         TreeSet<Integer> moduleIndices = new TreeSet<>();
503                         int nullIndexFound = 0;
504                         for (VfModule vfModule : modules) {
505                                 if (vfModule.getModelInfoVfModule() != null) {
506                                         if (vfModule.getModelInfoVfModule().getModelInvariantUUID().equals(newVfModuleModelInvariantUUID)) {
507                                                 if (vfModule.getModuleIndex() != null) {
508                                                         moduleIndices.add(vfModule.getModuleIndex());
509                                                 } else {
510                                                         nullIndexFound++;
511                                                         logger.warn("Found null index for vf-module-id {} and model-invariant-uuid {}", vfModule.getVfModuleId(), vfModule.getModelInfoVfModule().getModelInvariantUUID());
512                                                 }
513                                         }
514                                 }
515                         }
516                         
517                         return calculateUnusedIndex(moduleIndices, nullIndexFound);
518                 } else {
519                         return 0;
520                 }
521         }
522         
523         protected int calculateUnusedIndex(TreeSet<Integer> moduleIndices, int nullIndexFound) {
524                 //pad array with nulls
525                 Integer[] temp = new Integer[moduleIndices.size() + nullIndexFound];
526                 Integer[] array = moduleIndices.toArray(temp);
527                 int result = 0;
528                 //when a null is found skip that potential value
529                 //effectively creates something like, [0,1,3,null,null] -> [0,1,null(2),3,null(4)]
530                 for (int i=0; i < array.length; i++, result++) {
531                         if (Integer.valueOf(result) != array[i]) {
532                                 if (nullIndexFound > 0) {
533                                         nullIndexFound--;
534                                         i--;
535                                 } else {
536                                         break;
537                                 }
538                         }
539                 }
540                 
541                 return result;
542         }
543 }