Merge "Fix sonar issues in mso-openstack-adapters"
[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  * Modifications Copyright (c) 2019 Samsung
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.aai.tasks;
24
25 import java.util.Arrays;
26 import java.util.List;
27 import java.util.Optional;
28 import java.util.TreeSet;
29 import java.util.UUID;
30 import java.util.stream.Collectors;
31 import java.util.stream.Stream;
32 import org.onap.so.logger.LoggingAnchor;
33 import org.camunda.bpm.engine.delegate.BpmnError;
34 import org.onap.so.bpmn.common.BuildingBlockExecution;
35 import org.onap.so.bpmn.servicedecomposition.bbobjects.CloudRegion;
36 import org.onap.so.bpmn.servicedecomposition.bbobjects.Collection;
37 import org.onap.so.bpmn.servicedecomposition.bbobjects.Configuration;
38 import org.onap.so.bpmn.servicedecomposition.bbobjects.Customer;
39 import org.onap.so.bpmn.servicedecomposition.bbobjects.GenericVnf;
40 import org.onap.so.bpmn.servicedecomposition.bbobjects.InstanceGroup;
41 import org.onap.so.bpmn.servicedecomposition.bbobjects.L3Network;
42 import org.onap.so.bpmn.servicedecomposition.bbobjects.LineOfBusiness;
43 import org.onap.so.bpmn.servicedecomposition.bbobjects.NetworkPolicy;
44 import org.onap.so.bpmn.servicedecomposition.bbobjects.OwningEntity;
45 import org.onap.so.bpmn.servicedecomposition.bbobjects.Platform;
46 import org.onap.so.bpmn.servicedecomposition.bbobjects.Project;
47 import org.onap.so.bpmn.servicedecomposition.bbobjects.ServiceInstance;
48 import org.onap.so.bpmn.servicedecomposition.bbobjects.VfModule;
49 import org.onap.so.bpmn.servicedecomposition.bbobjects.VolumeGroup;
50 import org.onap.so.bpmn.servicedecomposition.entities.GeneralBuildingBlock;
51 import org.onap.so.bpmn.servicedecomposition.entities.ResourceKey;
52 import org.onap.so.bpmn.servicedecomposition.tasks.ExtractPojosForBB;
53 import org.onap.so.bpmn.servicedecomposition.tasks.exceptions.DuplicateNameException;
54 import org.onap.so.client.aai.AAIObjectPlurals;
55 import org.onap.so.client.aai.entities.uri.AAIResourceUri;
56 import org.onap.so.client.aai.entities.uri.AAIUriFactory;
57 import org.onap.so.client.exception.BBObjectNotFoundException;
58 import org.onap.so.client.exception.ExceptionBuilder;
59 import org.onap.so.client.orchestration.AAIConfigurationResources;
60 import org.onap.so.client.orchestration.AAIInstanceGroupResources;
61 import org.onap.so.client.orchestration.AAINetworkResources;
62 import org.onap.so.client.orchestration.AAIServiceInstanceResources;
63 import org.onap.so.client.orchestration.AAIVfModuleResources;
64 import org.onap.so.client.orchestration.AAIVnfResources;
65 import org.onap.so.client.orchestration.AAIVolumeGroupResources;
66 import org.onap.so.client.orchestration.AAIVpnBindingResources;
67 import org.onap.so.logger.ErrorCode;
68 import org.onap.so.logger.MessageEnum;
69 import org.slf4j.Logger;
70 import org.slf4j.LoggerFactory;
71 import org.springframework.beans.factory.annotation.Autowired;
72 import org.springframework.core.env.Environment;
73 import org.springframework.stereotype.Component;
74
75 @Component
76 public class AAICreateTasks {
77
78     private static final Logger logger = LoggerFactory.getLogger(AAICreateTasks.class);
79     private static final String networkTypeProvider = "PROVIDER";
80     private static final String A_LA_CARTE = "aLaCarte";
81     private static String NETWORK_COLLECTION_NAME = "networkCollectionName";
82     private static String CONTRAIL_NETWORK_POLICY_FQDN_LIST = "contrailNetworkPolicyFqdnList";
83     private static String HEAT_STACK_ID = "heatStackId";
84     private static String NETWORK_POLICY_FQDN_PARAM = "network-policy-fqdn";
85     @Autowired
86     private AAIServiceInstanceResources aaiSIResources;
87     @Autowired
88     private AAIVnfResources aaiVnfResources;
89     @Autowired
90     private ExceptionBuilder exceptionUtil;
91     @Autowired
92     private ExtractPojosForBB extractPojosForBB;
93     @Autowired
94     private AAIVolumeGroupResources aaiVolumeGroupResources;
95     @Autowired
96     private AAIVfModuleResources aaiVfModuleResources;
97     @Autowired
98     private AAINetworkResources aaiNetworkResources;
99     @Autowired
100     private AAIVpnBindingResources aaiVpnBindingResources;
101     @Autowired
102     private AAIConfigurationResources aaiConfigurationResources;
103     @Autowired
104     private AAIInstanceGroupResources aaiInstanceGroupResources;
105     @Autowired
106     private Environment env;
107
108     public void createServiceInstance(BuildingBlockExecution execution) {
109         try {
110             Boolean alaCarte = execution.getVariable(A_LA_CARTE);
111             ServiceInstance serviceInstance =
112                     extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID);
113             if (Boolean.TRUE.equals(alaCarte) && aaiSIResources.checkInstanceServiceNameInUse(serviceInstance)) {
114                 throw new DuplicateNameException("service-instance", serviceInstance.getServiceInstanceName());
115             }
116             Customer customer = execution.getGeneralBuildingBlock().getCustomer();
117             aaiSIResources.createServiceInstance(serviceInstance, customer);
118         } catch (Exception ex) {
119             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
120         }
121     }
122
123     public void createServiceSubscription(BuildingBlockExecution execution) {
124         try {
125             ServiceInstance serviceInstance =
126                     extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID);
127             Customer customer = execution.getGeneralBuildingBlock().getCustomer();
128             if (null == customer) {
129                 String errorMessage =
130                         "Exception in creating ServiceSubscription. Customer not present for ServiceInstanceID: "
131                                 + serviceInstance.getServiceInstanceId();
132                 logger.error(LoggingAnchor.FIVE, MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), errorMessage,
133                         "BPMN", ErrorCode.UnknownError.getValue(), errorMessage);
134                 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, errorMessage);
135             }
136             aaiSIResources.createServiceSubscription(customer);
137         } catch (BpmnError ex) {
138             throw ex;
139         } catch (Exception ex) {
140             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
141         }
142     }
143
144     public void createProject(BuildingBlockExecution execution) {
145         try {
146             ServiceInstance serviceInstance =
147                     extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID);
148             Project project = serviceInstance.getProject();
149             if (project != null) {
150                 if (project.getProjectName() == null || "".equals(project.getProjectName())) {
151                     logger.info("ProjectName is null in input. Skipping create project...");
152                 } else {
153                     aaiSIResources.createProjectandConnectServiceInstance(project, serviceInstance);
154                 }
155             }
156         } catch (Exception ex) {
157             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
158         }
159     }
160
161     public void createOwningEntity(BuildingBlockExecution execution) {
162         try {
163             ServiceInstance serviceInstance =
164                     extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID);
165             OwningEntity owningEntity = serviceInstance.getOwningEntity();
166             String owningEntityId = owningEntity.getOwningEntityId();
167             String owningEntityName = owningEntity.getOwningEntityName();
168             if (owningEntityId == null || "".equals(owningEntityId)) {
169                 String msg = "Exception in AAICreateOwningEntity. OwningEntityId is null.";
170                 execution.setVariable("ErrorCreateOEAAI", msg);
171                 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg);
172             } else {
173                 if (aaiSIResources.existsOwningEntity(owningEntity)) {
174                     aaiSIResources.connectOwningEntityandServiceInstance(owningEntity, serviceInstance);
175                 } else {
176                     if (owningEntityName == null || "".equals(owningEntityName)) {
177                         String msg =
178                                 "Exception in AAICreateOwningEntity. Can't create an owningEntity with no owningEntityName.";
179                         logger.error(LoggingAnchor.FIVE, MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), msg, "BPMN",
180                                 ErrorCode.UnknownError.getValue(), msg);
181                         exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg);
182                     } else {
183                         if (aaiSIResources.existsOwningEntityName(owningEntityName)) {
184                             String msg =
185                                     "Exception in AAICreateOwningEntity. Can't create OwningEntity as name already exists in AAI associated with a different owning-entity-id (name must be unique)";
186                             logger.error(LoggingAnchor.FIVE, MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), msg,
187                                     "BPMN", ErrorCode.UnknownError.getValue(), msg);
188                             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg);
189                         } else {
190                             aaiSIResources.createOwningEntityandConnectServiceInstance(owningEntity, serviceInstance);
191                         }
192                     }
193                 }
194             }
195         } catch (Exception ex) {
196             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
197         }
198     }
199
200     public void createVnf(BuildingBlockExecution execution) {
201         try {
202             Boolean alaCarte = execution.getVariable(A_LA_CARTE);
203             GenericVnf vnf = extractPojosForBB.extractByKey(execution, ResourceKey.GENERIC_VNF_ID);
204             if (Boolean.TRUE.equals(alaCarte) && aaiVnfResources.checkNameInUse(vnf.getVnfName())) {
205                 throw new DuplicateNameException("generic-vnf", vnf.getVnfName());
206             }
207             ServiceInstance serviceInstance =
208                     extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID);
209             execution.setVariable("homing", Boolean.TRUE.equals(vnf.isCallHoming()));
210             aaiVnfResources.createVnfandConnectServiceInstance(vnf, serviceInstance);
211         } catch (Exception ex) {
212             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
213         }
214     }
215
216     public void createPlatform(BuildingBlockExecution execution) {
217         try {
218             GenericVnf vnf = extractPojosForBB.extractByKey(execution, ResourceKey.GENERIC_VNF_ID);
219             Platform platform = vnf.getPlatform();
220             if (platform != null) {
221                 if (platform.getPlatformName() == null || "".equals(platform.getPlatformName())) {
222                     logger.debug("PlatformName is null in input. Skipping create platform...");
223                 } else {
224                     List<String> platforms = splitCDL(platform.getPlatformName());
225                     platforms.stream().forEach(platformName -> aaiVnfResources
226                             .createPlatformandConnectVnf(new Platform(platformName), vnf));
227                 }
228             }
229         } catch (Exception ex) {
230             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
231         }
232
233     }
234
235     public List<String> splitCDL(String str) {
236         return Stream.of(str.split(",")).map(String::trim).map(elem -> new String(elem)).collect(Collectors.toList());
237     }
238
239     public void createLineOfBusiness(BuildingBlockExecution execution) {
240         try {
241             GenericVnf vnf = extractPojosForBB.extractByKey(execution, ResourceKey.GENERIC_VNF_ID);
242             LineOfBusiness lineOfBusiness = vnf.getLineOfBusiness();
243             if (lineOfBusiness != null) {
244                 if (lineOfBusiness.getLineOfBusinessName() == null
245                         || "".equals(lineOfBusiness.getLineOfBusinessName())) {
246                     logger.info("lineOfBusiness is null in input. Skipping create lineOfBusiness...");
247                 } else {
248                     List<String> lineOfBussinesses = splitCDL(lineOfBusiness.getLineOfBusinessName());
249                     lineOfBussinesses.stream().forEach(lobName -> aaiVnfResources
250                             .createLineOfBusinessandConnectVnf(new LineOfBusiness(lobName), vnf));
251                 }
252             }
253         } catch (Exception ex) {
254             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
255         }
256     }
257
258     public void createVolumeGroup(BuildingBlockExecution execution) {
259         try {
260             GeneralBuildingBlock gBBInput = execution.getGeneralBuildingBlock();
261
262             GenericVnf genericVnf = extractPojosForBB.extractByKey(execution, ResourceKey.GENERIC_VNF_ID);
263             VolumeGroup volumeGroup = extractPojosForBB.extractByKey(execution, ResourceKey.VOLUME_GROUP_ID);
264             CloudRegion cloudRegion = gBBInput.getCloudRegion();
265             Boolean alaCarte = execution.getVariable(A_LA_CARTE);
266             if (Boolean.TRUE.equals(alaCarte) && aaiVolumeGroupResources.checkNameInUse(volumeGroup)) {
267                 throw new DuplicateNameException("volume-group", volumeGroup.getVolumeGroupName());
268             }
269             aaiVolumeGroupResources.createVolumeGroup(volumeGroup, cloudRegion);
270             aaiVolumeGroupResources.connectVolumeGroupToVnf(genericVnf, volumeGroup, cloudRegion);
271             aaiVolumeGroupResources.connectVolumeGroupToTenant(volumeGroup, cloudRegion);
272         } catch (Exception ex) {
273             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
274         }
275     }
276
277     public void createVfModule(BuildingBlockExecution execution) {
278         try {
279             GenericVnf vnf = extractPojosForBB.extractByKey(execution, ResourceKey.GENERIC_VNF_ID);
280             VfModule vfModule = extractPojosForBB.extractByKey(execution, ResourceKey.VF_MODULE_ID);
281             Boolean alaCarte = execution.getVariable(A_LA_CARTE);
282             if (Boolean.TRUE.equals(alaCarte) && aaiVfModuleResources.checkNameInUse(vfModule)) {
283                 throw new DuplicateNameException("vf-module", vfModule.getVfModuleName());
284             }
285             int moduleIndex = 0;
286             if (vfModule.getModelInfoVfModule() != null
287                     && !Boolean.TRUE.equals(vfModule.getModelInfoVfModule().getIsBaseBoolean())) {
288                 moduleIndex = this.getLowestUnusedVfModuleIndexFromAAIVnfResponse(vnf, vfModule);
289             }
290             vfModule.setModuleIndex(moduleIndex);
291             aaiVfModuleResources.createVfModule(vfModule, vnf);
292         } catch (Exception ex) {
293             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
294         }
295     }
296
297     /**
298      * BPMN access method to establish relationships in AAI
299      * 
300      * @param execution
301      * @throws Exception
302      */
303     public void connectVfModuleToVolumeGroup(BuildingBlockExecution execution) {
304         try {
305             GenericVnf vnf = extractPojosForBB.extractByKey(execution, ResourceKey.GENERIC_VNF_ID);
306             VfModule vfModule = extractPojosForBB.extractByKey(execution, ResourceKey.VF_MODULE_ID);
307             VolumeGroup volumeGroup = null;
308             try {
309                 volumeGroup = extractPojosForBB.extractByKey(execution, ResourceKey.VOLUME_GROUP_ID);
310             } catch (BBObjectNotFoundException e) {
311                 logger.info("VolumeGroup not found. Skipping Connect between VfModule and VolumeGroup");
312             }
313             if (volumeGroup != null) {
314                 aaiVfModuleResources.connectVfModuleToVolumeGroup(vnf, vfModule, volumeGroup,
315                         execution.getGeneralBuildingBlock().getCloudRegion());
316             }
317         } catch (Exception ex) {
318             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
319         }
320     }
321
322     /**
323      * BPMN access method to execute Create L3Network operation (PUT )in AAI
324      * 
325      * @param execution
326      * @throws Exception
327      */
328     public void createNetwork(BuildingBlockExecution execution) {
329         try {
330             Boolean alaCarte = execution.getVariable(A_LA_CARTE);
331             ServiceInstance serviceInstance =
332                     extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID);
333             L3Network l3network = extractPojosForBB.extractByKey(execution, ResourceKey.NETWORK_ID);
334             if (Boolean.TRUE.equals(alaCarte)
335                     && aaiNetworkResources.checkNetworkNameInUse(l3network.getNetworkName())) {
336                 throw new DuplicateNameException("l3Network", l3network.getNetworkName());
337             }
338             // set default to false. ToBe updated by SDNC
339             l3network.setIsBoundToVpn(false);
340             // define is bound to vpn flag as true if NEUTRON_NETWORK_TYPE is PROVIDER
341             if (l3network.getModelInfoNetwork().getNeutronNetworkType().equalsIgnoreCase(networkTypeProvider))
342                 l3network.setIsBoundToVpn(true);
343             // put network shell in AAI
344             aaiNetworkResources.createNetworkConnectToServiceInstance(l3network, serviceInstance);
345         } catch (Exception ex) {
346             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
347         }
348     }
349
350     public void createCustomer(BuildingBlockExecution execution) throws Exception {
351         try {
352             Customer customer = execution.getGeneralBuildingBlock().getCustomer();
353
354             aaiVpnBindingResources.createCustomer(customer);
355         } catch (Exception ex) {
356             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
357         }
358     }
359
360     /**
361      * BPMN access method to execute NetworkCollection operation (PUT) in AAI
362      * 
363      * @param execution
364      * @throws Exception
365      */
366     public void createNetworkCollection(BuildingBlockExecution execution) {
367         try {
368             ServiceInstance serviceInstance =
369                     extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID);
370             Collection networkCollection = serviceInstance.getCollection();
371             // pass name generated for NetworkCollection/NetworkCollectionInstanceGroup in previous step of the BB flow
372             // put shell in AAI
373             networkCollection.setName(execution.getVariable(NETWORK_COLLECTION_NAME));
374             aaiNetworkResources.createNetworkCollection(networkCollection);
375         } catch (Exception ex) {
376             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
377         }
378     }
379
380     /**
381      * BPMN access method to execute NetworkCollectionInstanceGroup operation (PUT) in AAI
382      * 
383      * @param execution
384      * @throws Exception
385      */
386     public void createNetworkCollectionInstanceGroup(BuildingBlockExecution execution) {
387         try {
388             Boolean alaCarte = execution.getVariable(A_LA_CARTE);
389             ServiceInstance serviceInstance =
390                     extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID);
391             InstanceGroup instanceGroup = serviceInstance.getCollection().getInstanceGroup();
392             // set name generated for NetworkCollection/NetworkCollectionInstanceGroup in previous step of the BB flow
393             instanceGroup.setInstanceGroupName(execution.getVariable(NETWORK_COLLECTION_NAME));
394             if (Boolean.TRUE.equals(alaCarte)
395                     && aaiInstanceGroupResources.checkInstanceGroupNameInUse(instanceGroup.getInstanceGroupName())) {
396                 throw new DuplicateNameException("instance-group", instanceGroup.getInstanceGroupName());
397             }
398             // put shell in AAI
399             aaiNetworkResources.createNetworkInstanceGroup(instanceGroup);
400         } catch (Exception ex) {
401             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
402         }
403     }
404
405
406     /**
407      * BPMN access method to establish relationships in AAI
408      * 
409      * @param execution
410      * @throws Exception
411      */
412     public void connectNetworkToTenant(BuildingBlockExecution execution) {
413         try {
414             L3Network l3network = extractPojosForBB.extractByKey(execution, ResourceKey.NETWORK_ID);
415             aaiNetworkResources.connectNetworkToTenant(l3network, execution.getGeneralBuildingBlock().getCloudRegion());
416         } catch (Exception ex) {
417             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
418         }
419     }
420
421     /**
422      * BPMN access method to establish relationships in AAI
423      * 
424      * @param execution
425      * @throws Exception
426      */
427     public void connectNetworkToCloudRegion(BuildingBlockExecution execution) {
428         try {
429             L3Network l3network = extractPojosForBB.extractByKey(execution, ResourceKey.NETWORK_ID);
430             aaiNetworkResources.connectNetworkToCloudRegion(l3network,
431                     execution.getGeneralBuildingBlock().getCloudRegion());
432         } catch (Exception ex) {
433             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
434         }
435     }
436
437     /**
438      * BPMN access method to establish relationships in AAI
439      * 
440      * @param execution
441      * @throws Exception
442      */
443     public void connectVnfToCloudRegion(BuildingBlockExecution execution) {
444         try {
445             boolean cloudRegionsToSkip = false;
446             String[] cloudRegions = env.getProperty("mso.bpmn.cloudRegionIdsToSkipAddingVnfEdgesTo", String[].class);
447             if (cloudRegions != null) {
448                 cloudRegionsToSkip = Arrays.stream(cloudRegions)
449                         .anyMatch(execution.getGeneralBuildingBlock().getCloudRegion().getLcpCloudRegionId()::equals);
450             }
451             if (!cloudRegionsToSkip) {
452                 GenericVnf vnf = extractPojosForBB.extractByKey(execution, ResourceKey.GENERIC_VNF_ID);
453                 aaiVnfResources.connectVnfToCloudRegion(vnf, execution.getGeneralBuildingBlock().getCloudRegion());
454             }
455         } catch (Exception ex) {
456             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
457         }
458     }
459
460     /**
461      * BPMN access method to establish relationships in AAI
462      * 
463      * @param execution
464      * @throws Exception
465      */
466     public void connectVnfToTenant(BuildingBlockExecution execution) {
467         try {
468             GenericVnf vnf = extractPojosForBB.extractByKey(execution, ResourceKey.GENERIC_VNF_ID);
469             aaiVnfResources.connectVnfToTenant(vnf, execution.getGeneralBuildingBlock().getCloudRegion());
470         } catch (Exception ex) {
471             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
472         }
473     }
474
475     /**
476      * BPMN access method to establish relationships in AAI
477      * 
478      * @param execution
479      * @throws Exception
480      */
481     public void connectNetworkToNetworkCollectionServiceInstance(BuildingBlockExecution execution) {
482         try {
483             ServiceInstance serviceInstance =
484                     extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID);
485             L3Network l3network = extractPojosForBB.extractByKey(execution, ResourceKey.NETWORK_ID);
486             aaiNetworkResources.connectNetworkToNetworkCollectionServiceInstance(l3network, serviceInstance);
487         } catch (Exception ex) {
488             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
489         }
490     }
491
492     /**
493      * BPMN access method to establish relationships in AAI
494      * 
495      * @param execution
496      * @throws Exception
497      */
498     public void connectNetworkToNetworkCollectionInstanceGroup(BuildingBlockExecution execution) {
499         try {
500             ServiceInstance serviceInstance =
501                     extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID);
502             L3Network l3network = extractPojosForBB.extractByKey(execution, ResourceKey.NETWORK_ID);
503             // connect network only if Instance Group / Collection objects exist
504             if (serviceInstance.getCollection() != null && serviceInstance.getCollection().getInstanceGroup() != null)
505                 aaiNetworkResources.connectNetworkToNetworkCollectionInstanceGroup(l3network,
506                         serviceInstance.getCollection().getInstanceGroup());
507         } catch (Exception ex) {
508             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
509         }
510     }
511
512     public void createConfiguration(BuildingBlockExecution execution) {
513         try {
514             Boolean alaCarte = execution.getVariable(A_LA_CARTE);
515             Configuration configuration = extractPojosForBB.extractByKey(execution, ResourceKey.CONFIGURATION_ID);
516             if (Boolean.TRUE.equals(alaCarte)
517                     && aaiConfigurationResources.checkConfigurationNameInUse(configuration.getConfigurationName())) {
518                 throw new DuplicateNameException("configuration", configuration.getConfigurationName());
519             }
520             aaiConfigurationResources.createConfiguration(configuration);
521         } catch (Exception ex) {
522             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
523         }
524     }
525
526     public void createInstanceGroupVnf(BuildingBlockExecution execution) {
527         try {
528             Boolean alaCarte = execution.getVariable(A_LA_CARTE);
529             ServiceInstance serviceInstance =
530                     extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID);
531             InstanceGroup instanceGroup = extractPojosForBB.extractByKey(execution, ResourceKey.INSTANCE_GROUP_ID);
532             if (Boolean.TRUE.equals(alaCarte)
533                     && aaiInstanceGroupResources.checkInstanceGroupNameInUse(instanceGroup.getInstanceGroupName())) {
534                 throw new DuplicateNameException("instance-group", instanceGroup.getInstanceGroupName());
535             }
536             aaiInstanceGroupResources.createInstanceGroupandConnectServiceInstance(instanceGroup, serviceInstance);
537         } catch (Exception ex) {
538             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
539         }
540     }
541
542     public void createNetworkPolicies(BuildingBlockExecution execution) {
543         try {
544             String fqdns = execution.getVariable(CONTRAIL_NETWORK_POLICY_FQDN_LIST);
545             if (fqdns != null && !fqdns.isEmpty()) {
546                 String fqdnList[] = fqdns.split(",");
547                 int fqdnCount = fqdnList.length;
548                 if (fqdnCount > 0) {
549                     for (int i = 0; i < fqdnCount; i++) {
550                         String fqdn = fqdnList[i];
551                         AAIResourceUri uri = AAIUriFactory.createResourceUri(AAIObjectPlurals.NETWORK_POLICY);
552                         uri.queryParam(NETWORK_POLICY_FQDN_PARAM, fqdn);
553                         Optional<org.onap.aai.domain.yang.NetworkPolicy> oNetPolicy =
554                                 aaiNetworkResources.getNetworkPolicy(uri);
555                         if (!oNetPolicy.isPresent()) {
556                             logger.debug("This network policy FQDN is not in AAI yet: {}", fqdn);
557                             String networkPolicyId = UUID.randomUUID().toString();
558                             logger.debug("Adding network-policy with network-policy-id {}", networkPolicyId);
559                             NetworkPolicy networkPolicy = new NetworkPolicy();
560                             networkPolicy.setNetworkPolicyId(networkPolicyId);
561                             networkPolicy.setNetworkPolicyFqdn(fqdn);
562                             networkPolicy.setHeatStackId(execution.getVariable(HEAT_STACK_ID));
563
564                             aaiNetworkResources.createNetworkPolicy(networkPolicy);
565                         }
566                     }
567                 }
568             }
569         } catch (Exception ex) {
570             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
571         }
572     }
573
574     /**
575      * Groups existing vf modules by the model uuid of our new vf module and returns the lowest unused index
576      * 
577      * if we have a module type A, and there are 3 instances of those, and then module type B has 2 instances, if we are
578      * adding a new module type A, the vf-module-index should be 3 assuming contiguous indices (not 5, or 2)
579      * 
580      */
581     protected int getLowestUnusedVfModuleIndexFromAAIVnfResponse(GenericVnf genericVnf, VfModule newVfModule) {
582
583         String newVfModuleModelInvariantUUID = null;
584         if (newVfModule.getModelInfoVfModule() != null) {
585             newVfModuleModelInvariantUUID = newVfModule.getModelInfoVfModule().getModelInvariantUUID();
586         }
587
588
589         if (genericVnf != null && genericVnf.getVfModules() != null && !genericVnf.getVfModules().isEmpty()) {
590             List<VfModule> modules = genericVnf.getVfModules().stream()
591                     .filter(item -> !item.getVfModuleId().equals(newVfModule.getVfModuleId()))
592                     .collect(Collectors.toList());
593             TreeSet<Integer> moduleIndices = new TreeSet<>();
594             int nullIndexFound = 0;
595             for (VfModule vfModule : modules) {
596                 if (vfModule.getModelInfoVfModule() != null) {
597                     if (vfModule.getModelInfoVfModule().getModelInvariantUUID().equals(newVfModuleModelInvariantUUID)) {
598                         if (vfModule.getModuleIndex() != null) {
599                             moduleIndices.add(vfModule.getModuleIndex());
600                         } else {
601                             nullIndexFound++;
602                             logger.warn("Found null index for vf-module-id {} and model-invariant-uuid {}",
603                                     vfModule.getVfModuleId(), vfModule.getModelInfoVfModule().getModelInvariantUUID());
604                         }
605                     }
606                 }
607             }
608
609             return calculateUnusedIndex(moduleIndices, nullIndexFound);
610         } else {
611             return 0;
612         }
613     }
614
615     protected int calculateUnusedIndex(TreeSet<Integer> moduleIndices, int nullIndexFound) {
616         // pad array with nulls
617         Integer[] temp = new Integer[moduleIndices.size() + nullIndexFound];
618         Integer[] array = moduleIndices.toArray(temp);
619         int result = 0;
620         // when a null is found skip that potential value
621         // effectively creates something like, [0,1,3,null,null] -> [0,1,null(2),3,null(4)]
622         for (int i = 0; i < array.length; i++, result++) {
623             if (Integer.valueOf(result) != array[i]) {
624                 if (nullIndexFound > 0) {
625                     nullIndexFound--;
626                     i--;
627                 } else {
628                     break;
629                 }
630             }
631         }
632
633         return result;
634     }
635 }