possibility to use inventoried PNF instance in new service instance
[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  * Modifications Copyright (c) 2020 Nokia
10  * ================================================================================
11  * Licensed under the Apache License, Version 2.0 (the "License");
12  * you may not use this file except in compliance with the License.
13  * You may obtain a copy of the License at
14  * 
15  *      http://www.apache.org/licenses/LICENSE-2.0
16  * 
17  * Unless required by applicable law or agreed to in writing, software
18  * distributed under the License is distributed on an "AS IS" BASIS,
19  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20  * See the License for the specific language governing permissions and
21  * limitations under the License.
22  * ============LICENSE_END=========================================================
23  */
24
25 package org.onap.so.bpmn.infrastructure.aai.tasks;
26
27 import java.util.Arrays;
28 import java.util.List;
29 import java.util.Optional;
30 import java.util.TreeSet;
31 import java.util.UUID;
32 import java.util.stream.Collectors;
33 import java.util.stream.Stream;
34 import org.camunda.bpm.engine.delegate.BpmnError;
35 import org.onap.so.bpmn.common.BuildingBlockExecution;
36 import org.onap.so.bpmn.servicedecomposition.bbobjects.CloudRegion;
37 import org.onap.so.bpmn.servicedecomposition.bbobjects.Collection;
38 import org.onap.so.bpmn.servicedecomposition.bbobjects.Configuration;
39 import org.onap.so.bpmn.servicedecomposition.bbobjects.Customer;
40 import org.onap.so.bpmn.servicedecomposition.bbobjects.GenericVnf;
41 import org.onap.so.bpmn.servicedecomposition.bbobjects.InstanceGroup;
42 import org.onap.so.bpmn.servicedecomposition.bbobjects.L3Network;
43 import org.onap.so.bpmn.servicedecomposition.bbobjects.LineOfBusiness;
44 import org.onap.so.bpmn.servicedecomposition.bbobjects.NetworkPolicy;
45 import org.onap.so.bpmn.servicedecomposition.bbobjects.OwningEntity;
46 import org.onap.so.bpmn.servicedecomposition.bbobjects.Platform;
47 import org.onap.so.bpmn.servicedecomposition.bbobjects.Pnf;
48 import org.onap.so.bpmn.servicedecomposition.bbobjects.Project;
49 import org.onap.so.bpmn.servicedecomposition.bbobjects.ServiceInstance;
50 import org.onap.so.bpmn.servicedecomposition.bbobjects.VfModule;
51 import org.onap.so.bpmn.servicedecomposition.bbobjects.VolumeGroup;
52 import org.onap.so.bpmn.servicedecomposition.entities.GeneralBuildingBlock;
53 import org.onap.so.bpmn.servicedecomposition.entities.ResourceKey;
54 import org.onap.so.bpmn.servicedecomposition.tasks.ExtractPojosForBB;
55 import org.onap.aaiclient.client.aai.AAIObjectPlurals;
56 import org.onap.aaiclient.client.aai.entities.uri.AAIPluralResourceUri;
57 import org.onap.aaiclient.client.aai.entities.uri.AAIUriFactory;
58 import org.onap.so.client.exception.BBObjectNotFoundException;
59 import org.onap.so.client.exception.ExceptionBuilder;
60 import org.onap.so.client.orchestration.AAIConfigurationResources;
61 import org.onap.so.client.orchestration.AAIInstanceGroupResources;
62 import org.onap.so.client.orchestration.AAINetworkResources;
63 import org.onap.so.client.orchestration.AAIPnfResources;
64 import org.onap.so.client.orchestration.AAIServiceInstanceResources;
65 import org.onap.so.client.orchestration.AAIVfModuleResources;
66 import org.onap.so.client.orchestration.AAIVnfResources;
67 import org.onap.so.client.orchestration.AAIVolumeGroupResources;
68 import org.onap.so.client.orchestration.AAIVpnBindingResources;
69 import org.onap.logging.filter.base.ErrorCode;
70 import org.onap.so.logger.LoggingAnchor;
71 import org.onap.so.logger.MessageEnum;
72 import org.slf4j.Logger;
73 import org.slf4j.LoggerFactory;
74 import org.springframework.beans.factory.annotation.Autowired;
75 import org.springframework.core.env.Environment;
76 import org.springframework.stereotype.Component;
77 import com.google.common.base.Strings;
78
79 @Component
80 public class AAICreateTasks {
81
82     private static final Logger logger = LoggerFactory.getLogger(AAICreateTasks.class);
83     private static final String networkTypeProvider = "PROVIDER";
84     private static String NETWORK_COLLECTION_NAME = "networkCollectionName";
85     private static String CONTRAIL_NETWORK_POLICY_FQDN_LIST = "contrailNetworkPolicyFqdnList";
86     private static String HEAT_STACK_ID = "heatStackId";
87     private static String NETWORK_POLICY_FQDN_PARAM = "network-policy-fqdn";
88     @Autowired
89     private AAIServiceInstanceResources aaiSIResources;
90     @Autowired
91     private AAIVnfResources aaiVnfResources;
92     @Autowired
93     private AAIPnfResources aaiPnfResources;
94     @Autowired
95     private ExceptionBuilder exceptionUtil;
96     @Autowired
97     private ExtractPojosForBB extractPojosForBB;
98     @Autowired
99     private AAIVolumeGroupResources aaiVolumeGroupResources;
100     @Autowired
101     private AAIVfModuleResources aaiVfModuleResources;
102     @Autowired
103     private AAINetworkResources aaiNetworkResources;
104     @Autowired
105     private AAIVpnBindingResources aaiVpnBindingResources;
106     @Autowired
107     private AAIConfigurationResources aaiConfigurationResources;
108     @Autowired
109     private AAIInstanceGroupResources aaiInstanceGroupResources;
110     @Autowired
111     private Environment env;
112
113     /**
114      * This method is used for creating the service instance in A&AI.
115      *
116      * It will check the alaCarte and create the service instance in A&AI.
117      *
118      * @param execution
119      * @throws @return
120      */
121     public void createServiceInstance(BuildingBlockExecution execution) {
122         try {
123             ServiceInstance serviceInstance =
124                     extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID);
125             Customer customer = execution.getGeneralBuildingBlock().getCustomer();
126             aaiSIResources.createServiceInstance(serviceInstance, customer);
127         } catch (Exception ex) {
128             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
129         }
130     }
131
132     /**
133      * This method is used for creating and subscribing the service in A&AI.
134      *
135      * @param execution
136      * @throws @return
137      */
138     public void createServiceSubscription(BuildingBlockExecution execution) {
139         try {
140             ServiceInstance serviceInstance =
141                     extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID);
142             Customer customer = execution.getGeneralBuildingBlock().getCustomer();
143             if (null == customer) {
144                 String errorMessage =
145                         "Exception in creating ServiceSubscription. Customer not present for ServiceInstanceID: "
146                                 + serviceInstance.getServiceInstanceId();
147                 logger.error(LoggingAnchor.FIVE, MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), errorMessage,
148                         "BPMN", ErrorCode.UnknownError.getValue(), errorMessage);
149                 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, errorMessage);
150             }
151             aaiSIResources.createServiceSubscription(customer);
152         } catch (BpmnError ex) {
153             throw ex;
154         } catch (Exception ex) {
155             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
156         }
157     }
158
159     /**
160      * This method is used for creation of the project A&AI.
161      *
162      * @param execution
163      * @throws @return
164      */
165     public void createProject(BuildingBlockExecution execution) {
166         try {
167             ServiceInstance serviceInstance =
168                     extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID);
169             Project project = serviceInstance.getProject();
170             if (project != null) {
171                 if (project.getProjectName() == null || "".equals(project.getProjectName())) {
172                     logger.info("ProjectName is null in input. Skipping create project...");
173                 } else {
174                     aaiSIResources.createProjectandConnectServiceInstance(project, serviceInstance);
175                 }
176             }
177         } catch (Exception ex) {
178             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
179         }
180     }
181
182     /**
183      * This method is used for creating OwningEntity A&AI.
184      *
185      * @param execution
186      * @throws @return
187      */
188     public void createOwningEntity(BuildingBlockExecution execution) {
189         try {
190             ServiceInstance serviceInstance =
191                     extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID);
192             OwningEntity owningEntity = serviceInstance.getOwningEntity();
193             if (Strings.isNullOrEmpty(owningEntity.getOwningEntityId())
194                     && Strings.isNullOrEmpty(owningEntity.getOwningEntityName())) {
195                 String msg = "Exception in AAICreateOwningEntity. OwningEntityId and Name are null.";
196                 execution.setVariable("ErrorCreateOEAAI", msg);
197                 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg);
198             } else if (Strings.isNullOrEmpty(owningEntity.getOwningEntityId())
199                     && !Strings.isNullOrEmpty(owningEntity.getOwningEntityName())) {
200                 if (aaiSIResources.existsOwningEntityName(owningEntity.getOwningEntityName())) {
201                     org.onap.aai.domain.yang.OwningEntity aaiEntity =
202                             aaiSIResources.getOwningEntityByName(owningEntity.getOwningEntityName());
203                     owningEntity.setOwningEntityId(aaiEntity.getOwningEntityId());
204                     owningEntity.setOwningEntityName(owningEntity.getOwningEntityName());
205                     aaiSIResources.connectOwningEntityandServiceInstance(owningEntity, serviceInstance);
206                 } else {
207                     owningEntity.setOwningEntityId(UUID.randomUUID().toString());
208                     aaiSIResources.createOwningEntityandConnectServiceInstance(owningEntity, serviceInstance);
209                 }
210             } else {
211                 if (aaiSIResources.existsOwningEntity(owningEntity)) {
212                     aaiSIResources.connectOwningEntityandServiceInstance(owningEntity, serviceInstance);
213                 } else {
214                     if (Strings.isNullOrEmpty(owningEntity.getOwningEntityName())) {
215                         String msg =
216                                 "Exception in AAICreateOwningEntity. Can't create an owningEntity with no owningEntityName.";
217                         logger.error(LoggingAnchor.FIVE, MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), msg, "BPMN",
218                                 ErrorCode.UnknownError.getValue(), msg);
219                         exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg);
220                     } else {
221                         if (aaiSIResources.existsOwningEntityName(owningEntity.getOwningEntityName())) {
222                             String msg =
223                                     "Exception in AAICreateOwningEntity. Can't create OwningEntity as name already exists in AAI associated with a different owning-entity-id (name must be unique)";
224                             logger.error(LoggingAnchor.FIVE, MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), msg,
225                                     "BPMN", ErrorCode.UnknownError.getValue(), msg);
226                             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg);
227                         } else {
228                             aaiSIResources.createOwningEntityandConnectServiceInstance(owningEntity, serviceInstance);
229                         }
230                     }
231                 }
232             }
233         } catch (Exception ex) {
234             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
235         }
236     }
237
238     /**
239      * This method is used for creating Vnf in A&AI.
240      *
241      * It will check if the Vnf Name is exits in A&AI then it will throw the duplicate name exception.
242      *
243      * Otherwise it will create the vnf amd connect to the serviceinstance.
244      *
245      * @param execution
246      * @throws @return
247      */
248     public void createVnf(BuildingBlockExecution execution) {
249         try {
250             GenericVnf vnf = extractPojosForBB.extractByKey(execution, ResourceKey.GENERIC_VNF_ID);
251             ServiceInstance serviceInstance =
252                     extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID);
253             execution.setVariable("homing", Boolean.TRUE.equals(vnf.isCallHoming()));
254             aaiVnfResources.createVnfandConnectServiceInstance(vnf, serviceInstance);
255         } catch (Exception ex) {
256             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
257         }
258     }
259
260     public void createPnf(BuildingBlockExecution execution) {
261         try {
262             Pnf pnf = extractPojosForBB.extractByKey(execution, ResourceKey.PNF);
263             aaiPnfResources.checkIfPnfExistsInAaiAndCanBeUsed(pnf.getPnfName());
264             ServiceInstance serviceInstance =
265                     extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID);
266             aaiPnfResources.createPnfAndConnectServiceInstance(pnf, serviceInstance);
267         } catch (Exception e) {
268             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, e);
269         }
270     }
271
272     /**
273      * This method is used for separating (,) from the string.
274      *
275      * @param str
276      * @throws @return
277      */
278     public void createPlatformForNetwork(BuildingBlockExecution execution) {
279         try {
280             L3Network network = extractPojosForBB.extractByKey(execution, ResourceKey.NETWORK_ID);
281             if (network != null) {
282                 createPlatformNetwork(network);
283             }
284         } catch (Exception ex) {
285             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
286         }
287     }
288
289     /**
290      * This method is used for separating (,) from the string.
291      *
292      * @param str
293      * @throws @return
294      */
295     public void createPlatform(BuildingBlockExecution execution) {
296         try {
297             GenericVnf vnf = extractPojosForBB.extractByKey(execution, ResourceKey.GENERIC_VNF_ID);
298             if (vnf != null) {
299                 createPlatformVnf(vnf);
300             }
301         } catch (Exception ex) {
302             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
303         }
304
305     }
306
307     protected void createPlatformVnf(GenericVnf vnf) {
308         Platform platform = vnf.getPlatform();
309         if (Strings.isNullOrEmpty(platform.getPlatformName())) {
310             logger.debug("PlatformName is null in input. Skipping create platform...");
311         } else {
312             List<String> platforms = splitCDL(platform.getPlatformName());
313             platforms.stream().forEach(
314                     platformName -> aaiVnfResources.createPlatformandConnectVnf(new Platform(platformName), vnf));
315         }
316     }
317
318     protected void createPlatformNetwork(L3Network network) {
319         Platform platform = network.getPlatform();
320         if (platform != null) {
321             if (Strings.isNullOrEmpty(platform.getPlatformName())) {
322                 logger.debug("PlatformName is null in input. Skipping create platform...");
323             } else {
324                 List<String> platforms = splitCDL(platform.getPlatformName());
325                 platforms.stream().forEach(platformName -> aaiNetworkResources
326                         .createPlatformAndConnectNetwork(new Platform(platformName), network));
327             }
328         }
329     }
330
331     /**
332      * This method is used for separating (,) from the string.
333      *
334      * @param str
335      * @throws @return
336      */
337     public List<String> splitCDL(String str) {
338         return Stream.of(str.split(",")).map(String::trim).map(elem -> new String(elem)).collect(Collectors.toList());
339     }
340
341     /**
342      * This method is used for creating the type of business in A&AI.
343      *
344      * @param execution
345      * @throws @return
346      */
347     public void createLineOfBusiness(BuildingBlockExecution execution) {
348         try {
349             GenericVnf vnf = extractPojosForBB.extractByKey(execution, ResourceKey.GENERIC_VNF_ID);
350             if (vnf != null) {
351                 createLineOfBusinessVnf(vnf);
352             }
353         } catch (Exception ex) {
354             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
355         }
356     }
357
358     public void createLineOfBusinessForNetwork(BuildingBlockExecution execution) {
359         try {
360             L3Network network = extractPojosForBB.extractByKey(execution, ResourceKey.NETWORK_ID);
361             if (network != null) {
362                 createLineOfBusinessNetwork(network);
363             }
364         } catch (Exception ex) {
365             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
366         }
367     }
368
369     protected void createLineOfBusinessVnf(GenericVnf vnf) {
370         LineOfBusiness lineOfBusiness = vnf.getLineOfBusiness();
371         if (lineOfBusiness != null) {
372             if (Strings.isNullOrEmpty(lineOfBusiness.getLineOfBusinessName())) {
373                 logger.info("lineOfBusiness is null in input. Skipping create lineOfBusiness...");
374             } else {
375                 List<String> lineOfBussinesses = splitCDL(lineOfBusiness.getLineOfBusinessName());
376                 lineOfBussinesses.stream().forEach(
377                         lobName -> aaiVnfResources.createLineOfBusinessandConnectVnf(new LineOfBusiness(lobName), vnf));
378             }
379         }
380     }
381
382     protected void createLineOfBusinessNetwork(L3Network network) {
383         LineOfBusiness lineOfBusiness = network.getLineOfBusiness();
384         if (lineOfBusiness != null) {
385             if (Strings.isNullOrEmpty(lineOfBusiness.getLineOfBusinessName())) {
386                 logger.info("lineOfBusiness is null in input. Skipping create lineOfBusiness...");
387             } else {
388                 List<String> lineOfBussinesses = splitCDL(lineOfBusiness.getLineOfBusinessName());
389                 lineOfBussinesses.stream().forEach(lobName -> aaiNetworkResources
390                         .createLineOfBusinessAndConnectNetwork(new LineOfBusiness(lobName), network));
391             }
392         }
393     }
394
395     /**
396      * This method is used for creating the volume group in A&AI.
397      *
398      * @param execution
399      * @throws @return
400      */
401     public void createVolumeGroup(BuildingBlockExecution execution) {
402         try {
403             GeneralBuildingBlock gBBInput = execution.getGeneralBuildingBlock();
404
405             GenericVnf genericVnf = extractPojosForBB.extractByKey(execution, ResourceKey.GENERIC_VNF_ID);
406             VolumeGroup volumeGroup = extractPojosForBB.extractByKey(execution, ResourceKey.VOLUME_GROUP_ID);
407             CloudRegion cloudRegion = gBBInput.getCloudRegion();
408             aaiVolumeGroupResources.createVolumeGroup(volumeGroup, cloudRegion);
409             aaiVolumeGroupResources.connectVolumeGroupToVnf(genericVnf, volumeGroup, cloudRegion);
410             aaiVolumeGroupResources.connectVolumeGroupToTenant(volumeGroup, cloudRegion);
411         } catch (Exception ex) {
412             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
413         }
414     }
415
416     /**
417      * This method is used for creating the vfModule in A&AI.
418      *
419      * @param execution
420      * @throws @return
421      */
422     public void createVfModule(BuildingBlockExecution execution) {
423         try {
424             GenericVnf vnf = extractPojosForBB.extractByKey(execution, ResourceKey.GENERIC_VNF_ID);
425             VfModule vfModule = extractPojosForBB.extractByKey(execution, ResourceKey.VF_MODULE_ID);
426             int moduleIndex = 0;
427             if (vfModule.getModelInfoVfModule() != null
428                     && !Boolean.TRUE.equals(vfModule.getModelInfoVfModule().getIsBaseBoolean())) {
429                 moduleIndex = this.getLowestUnusedVfModuleIndexFromAAIVnfResponse(vnf, vfModule);
430             }
431             vfModule.setModuleIndex(moduleIndex);
432             aaiVfModuleResources.createVfModule(vfModule, vnf);
433         } catch (Exception ex) {
434             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
435         }
436     }
437
438     /**
439      * BPMN access method to establish relationships in AAI
440      *
441      * @param execution
442      * @throws Exception
443      */
444     public void connectVfModuleToVolumeGroup(BuildingBlockExecution execution) {
445         try {
446             GenericVnf vnf = extractPojosForBB.extractByKey(execution, ResourceKey.GENERIC_VNF_ID);
447             VfModule vfModule = extractPojosForBB.extractByKey(execution, ResourceKey.VF_MODULE_ID);
448             VolumeGroup volumeGroup = null;
449             try {
450                 volumeGroup = extractPojosForBB.extractByKey(execution, ResourceKey.VOLUME_GROUP_ID);
451             } catch (BBObjectNotFoundException e) {
452                 logger.info("VolumeGroup not found. Skipping Connect between VfModule and VolumeGroup");
453             }
454             if (volumeGroup != null) {
455                 logger.debug("Connecting VfModule to VolumGroup");
456                 aaiVfModuleResources.connectVfModuleToVolumeGroup(vnf, vfModule, volumeGroup,
457                         execution.getGeneralBuildingBlock().getCloudRegion());
458             }
459         } catch (Exception ex) {
460             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
461         }
462     }
463
464     /**
465      * BPMN access method to execute Create L3Network operation (PUT )in AAI
466      *
467      * @param execution
468      * @throws Exception
469      */
470     public void createNetwork(BuildingBlockExecution execution) {
471         try {
472             ServiceInstance serviceInstance =
473                     extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID);
474             L3Network l3network = extractPojosForBB.extractByKey(execution, ResourceKey.NETWORK_ID);
475             // set default to false. ToBe updated by SDNC
476             l3network.setIsBoundToVpn(false);
477             // define is bound to vpn flag as true if NEUTRON_NETWORK_TYPE is PROVIDER
478             if (l3network.getModelInfoNetwork().getNeutronNetworkType().equalsIgnoreCase(networkTypeProvider))
479                 l3network.setIsBoundToVpn(true);
480             // put network shell in AAI
481             aaiNetworkResources.createNetworkConnectToServiceInstance(l3network, serviceInstance);
482         } catch (Exception ex) {
483             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
484         }
485     }
486
487     /**
488      * This method is used for creating the customer in A&AI.
489      *
490      * @param execution
491      * @throws Exception
492      */
493     public void createCustomer(BuildingBlockExecution execution) throws Exception {
494         try {
495             Customer customer = execution.getGeneralBuildingBlock().getCustomer();
496
497             aaiVpnBindingResources.createCustomer(customer);
498         } catch (Exception ex) {
499             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
500         }
501     }
502
503     /**
504      * BPMN access method to execute NetworkCollection operation (PUT) in AAI
505      *
506      * @param execution
507      * @throws Exception
508      */
509     public void createNetworkCollection(BuildingBlockExecution execution) {
510         try {
511             ServiceInstance serviceInstance =
512                     extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID);
513             Collection networkCollection = serviceInstance.getCollection();
514             // pass name generated for NetworkCollection/NetworkCollectionInstanceGroup in previous step of the BB flow
515             // put shell in AAI
516             networkCollection.setName(execution.getVariable(NETWORK_COLLECTION_NAME));
517             aaiNetworkResources.createNetworkCollection(networkCollection);
518         } catch (Exception ex) {
519             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
520         }
521     }
522
523     /**
524      * BPMN access method to execute NetworkCollectionInstanceGroup operation (PUT) in AAI
525      *
526      * @param execution
527      * @throws Exception
528      */
529     public void createNetworkCollectionInstanceGroup(BuildingBlockExecution execution) {
530         try {
531             ServiceInstance serviceInstance =
532                     extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID);
533             InstanceGroup instanceGroup = serviceInstance.getCollection().getInstanceGroup();
534             // set name generated for NetworkCollection/NetworkCollectionInstanceGroup in previous step of the BB flow
535             instanceGroup.setInstanceGroupName(execution.getVariable(NETWORK_COLLECTION_NAME));
536             // put shell in AAI
537             aaiNetworkResources.createNetworkInstanceGroup(instanceGroup);
538         } catch (Exception ex) {
539             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
540         }
541     }
542
543
544     /**
545      * BPMN access method to establish relationships in AAI
546      *
547      * @param execution
548      * @throws Exception
549      */
550     public void connectNetworkToTenant(BuildingBlockExecution execution) {
551         try {
552             L3Network l3network = extractPojosForBB.extractByKey(execution, ResourceKey.NETWORK_ID);
553             aaiNetworkResources.connectNetworkToTenant(l3network, execution.getGeneralBuildingBlock().getCloudRegion());
554         } catch (Exception ex) {
555             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
556         }
557     }
558
559     /**
560      * BPMN access method to establish relationships in AAI
561      *
562      * @param execution
563      * @throws Exception
564      */
565     public void connectNetworkToCloudRegion(BuildingBlockExecution execution) {
566         try {
567             L3Network l3network = extractPojosForBB.extractByKey(execution, ResourceKey.NETWORK_ID);
568             aaiNetworkResources.connectNetworkToCloudRegion(l3network,
569                     execution.getGeneralBuildingBlock().getCloudRegion());
570         } catch (Exception ex) {
571             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
572         }
573     }
574
575     /**
576      * BPMN access method to establish relationships in AAI
577      *
578      * @param execution
579      * @throws Exception
580      */
581     public void connectVnfToCloudRegion(BuildingBlockExecution execution) {
582         try {
583             boolean cloudRegionsToSkip = false;
584             String[] cloudRegions = env.getProperty("mso.bpmn.cloudRegionIdsToSkipAddingVnfEdgesTo", String[].class);
585             if (cloudRegions != null) {
586                 cloudRegionsToSkip = Arrays.stream(cloudRegions)
587                         .anyMatch(execution.getGeneralBuildingBlock().getCloudRegion().getLcpCloudRegionId()::equals);
588             }
589             if (!cloudRegionsToSkip) {
590                 GenericVnf vnf = extractPojosForBB.extractByKey(execution, ResourceKey.GENERIC_VNF_ID);
591                 aaiVnfResources.connectVnfToCloudRegion(vnf, execution.getGeneralBuildingBlock().getCloudRegion());
592             }
593         } catch (Exception ex) {
594             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
595         }
596     }
597
598     /**
599      * BPMN access method to establish relationships in AAI
600      *
601      * @param execution
602      * @throws Exception
603      */
604     public void connectVnfToTenant(BuildingBlockExecution execution) {
605         try {
606             GenericVnf vnf = extractPojosForBB.extractByKey(execution, ResourceKey.GENERIC_VNF_ID);
607             aaiVnfResources.connectVnfToTenant(vnf, execution.getGeneralBuildingBlock().getCloudRegion());
608         } catch (Exception ex) {
609             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
610         }
611     }
612
613     /**
614      * BPMN access method to establish relationships in AAI
615      *
616      * @param execution
617      * @throws Exception
618      */
619     public void connectNetworkToNetworkCollectionServiceInstance(BuildingBlockExecution execution) {
620         try {
621             ServiceInstance serviceInstance =
622                     extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID);
623             L3Network l3network = extractPojosForBB.extractByKey(execution, ResourceKey.NETWORK_ID);
624             aaiNetworkResources.connectNetworkToNetworkCollectionServiceInstance(l3network, serviceInstance);
625         } catch (Exception ex) {
626             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
627         }
628     }
629
630     /**
631      * BPMN access method to establish relationships in AAI
632      *
633      * @param execution
634      * @throws Exception
635      */
636     public void connectNetworkToNetworkCollectionInstanceGroup(BuildingBlockExecution execution) {
637         try {
638             ServiceInstance serviceInstance =
639                     extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID);
640             L3Network l3network = extractPojosForBB.extractByKey(execution, ResourceKey.NETWORK_ID);
641             // connect network only if Instance Group / Collection objects exist
642             if (serviceInstance.getCollection() != null && serviceInstance.getCollection().getInstanceGroup() != null)
643                 aaiNetworkResources.connectNetworkToNetworkCollectionInstanceGroup(l3network,
644                         serviceInstance.getCollection().getInstanceGroup());
645         } catch (Exception ex) {
646             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
647         }
648     }
649
650     /**
651      * This method is used for configuring the service in A&AI.
652      *
653      * @param execution @throws
654      */
655     public void createConfiguration(BuildingBlockExecution execution) {
656         try {
657             Configuration configuration = extractPojosForBB.extractByKey(execution, ResourceKey.CONFIGURATION_ID);
658             aaiConfigurationResources.createConfiguration(configuration);
659         } catch (Exception ex) {
660             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
661         }
662     }
663
664     /**
665      * This method is used for creating vnf instance group in A&AI.
666      *
667      * @param execution @throws
668      */
669     public void createInstanceGroupVnf(BuildingBlockExecution execution) {
670         try {
671             ServiceInstance serviceInstance =
672                     extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID);
673             InstanceGroup instanceGroup = extractPojosForBB.extractByKey(execution, ResourceKey.INSTANCE_GROUP_ID);
674             aaiInstanceGroupResources.createInstanceGroupandConnectServiceInstance(instanceGroup, serviceInstance);
675         } catch (Exception ex) {
676             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
677         }
678     }
679
680     /**
681      * This method is used to put the network policy in A&AI.
682      *
683      * @param execution @throws
684      */
685     public void createNetworkPolicies(BuildingBlockExecution execution) {
686         try {
687             String fqdns = execution.getVariable(CONTRAIL_NETWORK_POLICY_FQDN_LIST);
688             if (fqdns != null && !fqdns.isEmpty()) {
689                 String fqdnList[] = fqdns.split(",");
690                 int fqdnCount = fqdnList.length;
691                 if (fqdnCount > 0) {
692                     for (int i = 0; i < fqdnCount; i++) {
693                         String fqdn = fqdnList[i];
694                         AAIPluralResourceUri uri = AAIUriFactory.createResourceUri(AAIObjectPlurals.NETWORK_POLICY);
695                         uri.queryParam(NETWORK_POLICY_FQDN_PARAM, fqdn);
696                         Optional<org.onap.aai.domain.yang.NetworkPolicy> oNetPolicy =
697                                 aaiNetworkResources.getNetworkPolicy(uri);
698                         if (!oNetPolicy.isPresent()) {
699                             logger.debug("This network policy FQDN is not in AAI yet: {}", fqdn);
700                             String networkPolicyId = UUID.randomUUID().toString();
701                             logger.debug("Adding network-policy with network-policy-id {}", networkPolicyId);
702                             NetworkPolicy networkPolicy = new NetworkPolicy();
703                             networkPolicy.setNetworkPolicyId(networkPolicyId);
704                             networkPolicy.setNetworkPolicyFqdn(fqdn);
705                             networkPolicy.setHeatStackId(execution.getVariable(HEAT_STACK_ID));
706
707                             aaiNetworkResources.createNetworkPolicy(networkPolicy);
708                         }
709                     }
710                 }
711             }
712         } catch (Exception ex) {
713             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
714         }
715     }
716
717     /**
718      * Groups existing vf modules by the model uuid of our new vf module and returns the lowest unused index
719      *
720      * 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
721      * adding a new module type A, the vf-module-index should be 3 assuming contiguous indices (not 5, or 2)
722      *
723      */
724     protected int getLowestUnusedVfModuleIndexFromAAIVnfResponse(GenericVnf genericVnf, VfModule newVfModule) {
725
726         String newVfModuleModelInvariantUUID = null;
727         if (newVfModule.getModelInfoVfModule() != null) {
728             newVfModuleModelInvariantUUID = newVfModule.getModelInfoVfModule().getModelInvariantUUID();
729         }
730
731
732         if (genericVnf != null && genericVnf.getVfModules() != null && !genericVnf.getVfModules().isEmpty()) {
733             List<VfModule> modules = genericVnf.getVfModules().stream()
734                     .filter(item -> !item.getVfModuleId().equals(newVfModule.getVfModuleId()))
735                     .collect(Collectors.toList());
736             TreeSet<Integer> moduleIndices = new TreeSet<>();
737             int nullIndexFound = 0;
738             for (VfModule vfModule : modules) {
739                 if (vfModule.getModelInfoVfModule() != null) {
740                     if (vfModule.getModelInfoVfModule().getModelInvariantUUID().equals(newVfModuleModelInvariantUUID)) {
741                         if (vfModule.getModuleIndex() != null) {
742                             moduleIndices.add(vfModule.getModuleIndex());
743                         } else {
744                             nullIndexFound++;
745                             logger.warn("Found null index for vf-module-id {} and model-invariant-uuid {}",
746                                     vfModule.getVfModuleId(), vfModule.getModelInfoVfModule().getModelInvariantUUID());
747                         }
748                     }
749                 }
750             }
751
752             return calculateUnusedIndex(moduleIndices, nullIndexFound);
753         } else {
754             return 0;
755         }
756     }
757
758     protected int calculateUnusedIndex(TreeSet<Integer> moduleIndices, int nullIndexFound) {
759         // pad array with nulls
760         Integer[] temp = new Integer[moduleIndices.size() + nullIndexFound];
761         Integer[] array = moduleIndices.toArray(temp);
762         int result = 0;
763         // when a null is found skip that potential value
764         // effectively creates something like, [0,1,3,null,null] -> [0,1,null(2),3,null(4)]
765         for (int i = 0; i < array.length; i++, result++) {
766             if (Integer.valueOf(result) != array[i]) {
767                 if (nullIndexFound > 0) {
768                     nullIndexFound--;
769                     i--;
770                 } else {
771                     break;
772                 }
773             }
774         }
775
776         return result;
777     }
778 }