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