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