385b96c0f8fcea974129c7bea8fe55f279bd6050
[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             ServiceInstance serviceInstance =
264                     extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID);
265             aaiPnfResources.createPnfAndConnectServiceInstance(pnf, serviceInstance);
266         } catch (BBObjectNotFoundException e) {
267             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, e);
268         }
269     }
270
271     /**
272      * This method is used for separating (,) from the string.
273      *
274      * @param str
275      * @throws @return
276      */
277     public void createPlatformForNetwork(BuildingBlockExecution execution) {
278         try {
279             L3Network network = extractPojosForBB.extractByKey(execution, ResourceKey.NETWORK_ID);
280             if (network != null) {
281                 createPlatformNetwork(network);
282             }
283         } catch (Exception ex) {
284             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
285         }
286     }
287
288     /**
289      * This method is used for separating (,) from the string.
290      *
291      * @param str
292      * @throws @return
293      */
294     public void createPlatform(BuildingBlockExecution execution) {
295         try {
296             GenericVnf vnf = extractPojosForBB.extractByKey(execution, ResourceKey.GENERIC_VNF_ID);
297             if (vnf != null) {
298                 createPlatformVnf(vnf);
299             }
300         } catch (Exception ex) {
301             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
302         }
303
304     }
305
306     protected void createPlatformVnf(GenericVnf vnf) {
307         Platform platform = vnf.getPlatform();
308         if (Strings.isNullOrEmpty(platform.getPlatformName())) {
309             logger.debug("PlatformName is null in input. Skipping create platform...");
310         } else {
311             List<String> platforms = splitCDL(platform.getPlatformName());
312             platforms.stream().forEach(
313                     platformName -> aaiVnfResources.createPlatformandConnectVnf(new Platform(platformName), vnf));
314         }
315     }
316
317     protected void createPlatformNetwork(L3Network network) {
318         Platform platform = network.getPlatform();
319         if (platform != null) {
320             if (Strings.isNullOrEmpty(platform.getPlatformName())) {
321                 logger.debug("PlatformName is null in input. Skipping create platform...");
322             } else {
323                 List<String> platforms = splitCDL(platform.getPlatformName());
324                 platforms.stream().forEach(platformName -> aaiNetworkResources
325                         .createPlatformAndConnectNetwork(new Platform(platformName), network));
326             }
327         }
328     }
329
330     /**
331      * This method is used for separating (,) from the string.
332      *
333      * @param str
334      * @throws @return
335      */
336     public List<String> splitCDL(String str) {
337         return Stream.of(str.split(",")).map(String::trim).map(elem -> new String(elem)).collect(Collectors.toList());
338     }
339
340     /**
341      * This method is used for creating the type of business in A&AI.
342      *
343      * @param execution
344      * @throws @return
345      */
346     public void createLineOfBusiness(BuildingBlockExecution execution) {
347         try {
348             GenericVnf vnf = extractPojosForBB.extractByKey(execution, ResourceKey.GENERIC_VNF_ID);
349             if (vnf != null) {
350                 createLineOfBusinessVnf(vnf);
351             }
352         } catch (Exception ex) {
353             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
354         }
355     }
356
357     public void createLineOfBusinessForNetwork(BuildingBlockExecution execution) {
358         try {
359             L3Network network = extractPojosForBB.extractByKey(execution, ResourceKey.NETWORK_ID);
360             if (network != null) {
361                 createLineOfBusinessNetwork(network);
362             }
363         } catch (Exception ex) {
364             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
365         }
366     }
367
368     protected void createLineOfBusinessVnf(GenericVnf vnf) {
369         LineOfBusiness lineOfBusiness = vnf.getLineOfBusiness();
370         if (lineOfBusiness != null) {
371             if (Strings.isNullOrEmpty(lineOfBusiness.getLineOfBusinessName())) {
372                 logger.info("lineOfBusiness is null in input. Skipping create lineOfBusiness...");
373             } else {
374                 List<String> lineOfBussinesses = splitCDL(lineOfBusiness.getLineOfBusinessName());
375                 lineOfBussinesses.stream().forEach(
376                         lobName -> aaiVnfResources.createLineOfBusinessandConnectVnf(new LineOfBusiness(lobName), vnf));
377             }
378         }
379     }
380
381     protected void createLineOfBusinessNetwork(L3Network network) {
382         LineOfBusiness lineOfBusiness = network.getLineOfBusiness();
383         if (lineOfBusiness != null) {
384             if (Strings.isNullOrEmpty(lineOfBusiness.getLineOfBusinessName())) {
385                 logger.info("lineOfBusiness is null in input. Skipping create lineOfBusiness...");
386             } else {
387                 List<String> lineOfBussinesses = splitCDL(lineOfBusiness.getLineOfBusinessName());
388                 lineOfBussinesses.stream().forEach(lobName -> aaiNetworkResources
389                         .createLineOfBusinessAndConnectNetwork(new LineOfBusiness(lobName), network));
390             }
391         }
392     }
393
394     /**
395      * This method is used for creating the volume group in A&AI.
396      *
397      * @param execution
398      * @throws @return
399      */
400     public void createVolumeGroup(BuildingBlockExecution execution) {
401         try {
402             GeneralBuildingBlock gBBInput = execution.getGeneralBuildingBlock();
403
404             GenericVnf genericVnf = extractPojosForBB.extractByKey(execution, ResourceKey.GENERIC_VNF_ID);
405             VolumeGroup volumeGroup = extractPojosForBB.extractByKey(execution, ResourceKey.VOLUME_GROUP_ID);
406             CloudRegion cloudRegion = gBBInput.getCloudRegion();
407             aaiVolumeGroupResources.createVolumeGroup(volumeGroup, cloudRegion);
408             aaiVolumeGroupResources.connectVolumeGroupToVnf(genericVnf, volumeGroup, cloudRegion);
409             aaiVolumeGroupResources.connectVolumeGroupToTenant(volumeGroup, cloudRegion);
410         } catch (Exception ex) {
411             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
412         }
413     }
414
415     /**
416      * This method is used for creating the vfModule in A&AI.
417      *
418      * @param execution
419      * @throws @return
420      */
421     public void createVfModule(BuildingBlockExecution execution) {
422         try {
423             GenericVnf vnf = extractPojosForBB.extractByKey(execution, ResourceKey.GENERIC_VNF_ID);
424             VfModule vfModule = extractPojosForBB.extractByKey(execution, ResourceKey.VF_MODULE_ID);
425             int moduleIndex = 0;
426             if (vfModule.getModelInfoVfModule() != null
427                     && !Boolean.TRUE.equals(vfModule.getModelInfoVfModule().getIsBaseBoolean())) {
428                 moduleIndex = this.getLowestUnusedVfModuleIndexFromAAIVnfResponse(vnf, vfModule);
429             }
430             vfModule.setModuleIndex(moduleIndex);
431             aaiVfModuleResources.createVfModule(vfModule, vnf);
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 connectVfModuleToVolumeGroup(BuildingBlockExecution execution) {
444         try {
445             GenericVnf vnf = extractPojosForBB.extractByKey(execution, ResourceKey.GENERIC_VNF_ID);
446             VfModule vfModule = extractPojosForBB.extractByKey(execution, ResourceKey.VF_MODULE_ID);
447             VolumeGroup volumeGroup = null;
448             try {
449                 volumeGroup = extractPojosForBB.extractByKey(execution, ResourceKey.VOLUME_GROUP_ID);
450             } catch (BBObjectNotFoundException e) {
451                 logger.info("VolumeGroup not found. Skipping Connect between VfModule and VolumeGroup");
452             }
453             if (volumeGroup != null) {
454                 logger.debug("Connecting VfModule to VolumGroup");
455                 aaiVfModuleResources.connectVfModuleToVolumeGroup(vnf, vfModule, volumeGroup,
456                         execution.getGeneralBuildingBlock().getCloudRegion());
457             }
458         } catch (Exception ex) {
459             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
460         }
461     }
462
463     /**
464      * BPMN access method to execute Create L3Network operation (PUT )in AAI
465      *
466      * @param execution
467      * @throws Exception
468      */
469     public void createNetwork(BuildingBlockExecution execution) {
470         try {
471             ServiceInstance serviceInstance =
472                     extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID);
473             L3Network l3network = extractPojosForBB.extractByKey(execution, ResourceKey.NETWORK_ID);
474             // set default to false. ToBe updated by SDNC
475             l3network.setIsBoundToVpn(false);
476             // define is bound to vpn flag as true if NEUTRON_NETWORK_TYPE is PROVIDER
477             if (l3network.getModelInfoNetwork().getNeutronNetworkType().equalsIgnoreCase(networkTypeProvider))
478                 l3network.setIsBoundToVpn(true);
479             // put network shell in AAI
480             aaiNetworkResources.createNetworkConnectToServiceInstance(l3network, serviceInstance);
481         } catch (Exception ex) {
482             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
483         }
484     }
485
486     /**
487      * This method is used for creating the customer in A&AI.
488      *
489      * @param execution
490      * @throws Exception
491      */
492     public void createCustomer(BuildingBlockExecution execution) throws Exception {
493         try {
494             Customer customer = execution.getGeneralBuildingBlock().getCustomer();
495
496             aaiVpnBindingResources.createCustomer(customer);
497         } catch (Exception ex) {
498             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
499         }
500     }
501
502     /**
503      * BPMN access method to execute NetworkCollection operation (PUT) in AAI
504      *
505      * @param execution
506      * @throws Exception
507      */
508     public void createNetworkCollection(BuildingBlockExecution execution) {
509         try {
510             ServiceInstance serviceInstance =
511                     extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID);
512             Collection networkCollection = serviceInstance.getCollection();
513             // pass name generated for NetworkCollection/NetworkCollectionInstanceGroup in previous step of the BB flow
514             // put shell in AAI
515             networkCollection.setName(execution.getVariable(NETWORK_COLLECTION_NAME));
516             aaiNetworkResources.createNetworkCollection(networkCollection);
517         } catch (Exception ex) {
518             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
519         }
520     }
521
522     /**
523      * BPMN access method to execute NetworkCollectionInstanceGroup operation (PUT) in AAI
524      *
525      * @param execution
526      * @throws Exception
527      */
528     public void createNetworkCollectionInstanceGroup(BuildingBlockExecution execution) {
529         try {
530             ServiceInstance serviceInstance =
531                     extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID);
532             InstanceGroup instanceGroup = serviceInstance.getCollection().getInstanceGroup();
533             // set name generated for NetworkCollection/NetworkCollectionInstanceGroup in previous step of the BB flow
534             instanceGroup.setInstanceGroupName(execution.getVariable(NETWORK_COLLECTION_NAME));
535             // put shell in AAI
536             aaiNetworkResources.createNetworkInstanceGroup(instanceGroup);
537         } catch (Exception ex) {
538             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
539         }
540     }
541
542
543     /**
544      * BPMN access method to establish relationships in AAI
545      *
546      * @param execution
547      * @throws Exception
548      */
549     public void connectNetworkToTenant(BuildingBlockExecution execution) {
550         try {
551             L3Network l3network = extractPojosForBB.extractByKey(execution, ResourceKey.NETWORK_ID);
552             aaiNetworkResources.connectNetworkToTenant(l3network, execution.getGeneralBuildingBlock().getCloudRegion());
553         } catch (Exception ex) {
554             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
555         }
556     }
557
558     /**
559      * BPMN access method to establish relationships in AAI
560      *
561      * @param execution
562      * @throws Exception
563      */
564     public void connectNetworkToCloudRegion(BuildingBlockExecution execution) {
565         try {
566             L3Network l3network = extractPojosForBB.extractByKey(execution, ResourceKey.NETWORK_ID);
567             aaiNetworkResources.connectNetworkToCloudRegion(l3network,
568                     execution.getGeneralBuildingBlock().getCloudRegion());
569         } catch (Exception ex) {
570             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
571         }
572     }
573
574     /**
575      * BPMN access method to establish relationships in AAI
576      *
577      * @param execution
578      * @throws Exception
579      */
580     public void connectVnfToCloudRegion(BuildingBlockExecution execution) {
581         try {
582             boolean cloudRegionsToSkip = false;
583             String[] cloudRegions = env.getProperty("mso.bpmn.cloudRegionIdsToSkipAddingVnfEdgesTo", String[].class);
584             if (cloudRegions != null) {
585                 cloudRegionsToSkip = Arrays.stream(cloudRegions)
586                         .anyMatch(execution.getGeneralBuildingBlock().getCloudRegion().getLcpCloudRegionId()::equals);
587             }
588             if (!cloudRegionsToSkip) {
589                 GenericVnf vnf = extractPojosForBB.extractByKey(execution, ResourceKey.GENERIC_VNF_ID);
590                 aaiVnfResources.connectVnfToCloudRegion(vnf, execution.getGeneralBuildingBlock().getCloudRegion());
591             }
592         } catch (Exception ex) {
593             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
594         }
595     }
596
597     /**
598      * BPMN access method to establish relationships in AAI
599      *
600      * @param execution
601      * @throws Exception
602      */
603     public void connectVnfToTenant(BuildingBlockExecution execution) {
604         try {
605             GenericVnf vnf = extractPojosForBB.extractByKey(execution, ResourceKey.GENERIC_VNF_ID);
606             aaiVnfResources.connectVnfToTenant(vnf, execution.getGeneralBuildingBlock().getCloudRegion());
607         } catch (Exception ex) {
608             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
609         }
610     }
611
612     /**
613      * BPMN access method to establish relationships in AAI
614      *
615      * @param execution
616      * @throws Exception
617      */
618     public void connectNetworkToNetworkCollectionServiceInstance(BuildingBlockExecution execution) {
619         try {
620             ServiceInstance serviceInstance =
621                     extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID);
622             L3Network l3network = extractPojosForBB.extractByKey(execution, ResourceKey.NETWORK_ID);
623             aaiNetworkResources.connectNetworkToNetworkCollectionServiceInstance(l3network, serviceInstance);
624         } catch (Exception ex) {
625             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
626         }
627     }
628
629     /**
630      * BPMN access method to establish relationships in AAI
631      *
632      * @param execution
633      * @throws Exception
634      */
635     public void connectNetworkToNetworkCollectionInstanceGroup(BuildingBlockExecution execution) {
636         try {
637             ServiceInstance serviceInstance =
638                     extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID);
639             L3Network l3network = extractPojosForBB.extractByKey(execution, ResourceKey.NETWORK_ID);
640             // connect network only if Instance Group / Collection objects exist
641             if (serviceInstance.getCollection() != null && serviceInstance.getCollection().getInstanceGroup() != null)
642                 aaiNetworkResources.connectNetworkToNetworkCollectionInstanceGroup(l3network,
643                         serviceInstance.getCollection().getInstanceGroup());
644         } catch (Exception ex) {
645             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
646         }
647     }
648
649     /**
650      * This method is used for configuring the service in A&AI.
651      *
652      * @param execution @throws
653      */
654     public void createConfiguration(BuildingBlockExecution execution) {
655         try {
656             Configuration configuration = extractPojosForBB.extractByKey(execution, ResourceKey.CONFIGURATION_ID);
657             aaiConfigurationResources.createConfiguration(configuration);
658         } catch (Exception ex) {
659             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
660         }
661     }
662
663     /**
664      * This method is used for creating vnf instance group in A&AI.
665      *
666      * @param execution @throws
667      */
668     public void createInstanceGroupVnf(BuildingBlockExecution execution) {
669         try {
670             ServiceInstance serviceInstance =
671                     extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID);
672             InstanceGroup instanceGroup = extractPojosForBB.extractByKey(execution, ResourceKey.INSTANCE_GROUP_ID);
673             aaiInstanceGroupResources.createInstanceGroupandConnectServiceInstance(instanceGroup, serviceInstance);
674         } catch (Exception ex) {
675             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
676         }
677     }
678
679     /**
680      * This method is used to put the network policy in A&AI.
681      *
682      * @param execution @throws
683      */
684     public void createNetworkPolicies(BuildingBlockExecution execution) {
685         try {
686             String fqdns = execution.getVariable(CONTRAIL_NETWORK_POLICY_FQDN_LIST);
687             if (fqdns != null && !fqdns.isEmpty()) {
688                 String fqdnList[] = fqdns.split(",");
689                 int fqdnCount = fqdnList.length;
690                 if (fqdnCount > 0) {
691                     for (int i = 0; i < fqdnCount; i++) {
692                         String fqdn = fqdnList[i];
693                         AAIPluralResourceUri uri = AAIUriFactory.createResourceUri(AAIObjectPlurals.NETWORK_POLICY);
694                         uri.queryParam(NETWORK_POLICY_FQDN_PARAM, fqdn);
695                         Optional<org.onap.aai.domain.yang.NetworkPolicy> oNetPolicy =
696                                 aaiNetworkResources.getNetworkPolicy(uri);
697                         if (!oNetPolicy.isPresent()) {
698                             logger.debug("This network policy FQDN is not in AAI yet: {}", fqdn);
699                             String networkPolicyId = UUID.randomUUID().toString();
700                             logger.debug("Adding network-policy with network-policy-id {}", networkPolicyId);
701                             NetworkPolicy networkPolicy = new NetworkPolicy();
702                             networkPolicy.setNetworkPolicyId(networkPolicyId);
703                             networkPolicy.setNetworkPolicyFqdn(fqdn);
704                             networkPolicy.setHeatStackId(execution.getVariable(HEAT_STACK_ID));
705
706                             aaiNetworkResources.createNetworkPolicy(networkPolicy);
707                         }
708                     }
709                 }
710             }
711         } catch (Exception ex) {
712             exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
713         }
714     }
715
716     /**
717      * Groups existing vf modules by the model uuid of our new vf module and returns the lowest unused index
718      *
719      * 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
720      * adding a new module type A, the vf-module-index should be 3 assuming contiguous indices (not 5, or 2)
721      *
722      */
723     protected int getLowestUnusedVfModuleIndexFromAAIVnfResponse(GenericVnf genericVnf, VfModule newVfModule) {
724
725         String newVfModuleModelInvariantUUID = null;
726         if (newVfModule.getModelInfoVfModule() != null) {
727             newVfModuleModelInvariantUUID = newVfModule.getModelInfoVfModule().getModelInvariantUUID();
728         }
729
730
731         if (genericVnf != null && genericVnf.getVfModules() != null && !genericVnf.getVfModules().isEmpty()) {
732             List<VfModule> modules = genericVnf.getVfModules().stream()
733                     .filter(item -> !item.getVfModuleId().equals(newVfModule.getVfModuleId()))
734                     .collect(Collectors.toList());
735             TreeSet<Integer> moduleIndices = new TreeSet<>();
736             int nullIndexFound = 0;
737             for (VfModule vfModule : modules) {
738                 if (vfModule.getModelInfoVfModule() != null) {
739                     if (vfModule.getModelInfoVfModule().getModelInvariantUUID().equals(newVfModuleModelInvariantUUID)) {
740                         if (vfModule.getModuleIndex() != null) {
741                             moduleIndices.add(vfModule.getModuleIndex());
742                         } else {
743                             nullIndexFound++;
744                             logger.warn("Found null index for vf-module-id {} and model-invariant-uuid {}",
745                                     vfModule.getVfModuleId(), vfModule.getModelInfoVfModule().getModelInvariantUUID());
746                         }
747                     }
748                 }
749             }
750
751             return calculateUnusedIndex(moduleIndices, nullIndexFound);
752         } else {
753             return 0;
754         }
755     }
756
757     protected int calculateUnusedIndex(TreeSet<Integer> moduleIndices, int nullIndexFound) {
758         // pad array with nulls
759         Integer[] temp = new Integer[moduleIndices.size() + nullIndexFound];
760         Integer[] array = moduleIndices.toArray(temp);
761         int result = 0;
762         // when a null is found skip that potential value
763         // effectively creates something like, [0,1,3,null,null] -> [0,1,null(2),3,null(4)]
764         for (int i = 0; i < array.length; i++, result++) {
765             if (Integer.valueOf(result) != array[i]) {
766                 if (nullIndexFound > 0) {
767                     nullIndexFound--;
768                     i--;
769                 } else {
770                     break;
771                 }
772             }
773         }
774
775         return result;
776     }
777 }