2 * ============LICENSE_START=======================================================
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
13 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
23 package org.onap.so.bpmn.infrastructure.aai.tasks;
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 com.google.common.base.Strings;
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.client.aai.AAIObjectPlurals;
54 import org.onap.so.client.aai.entities.uri.AAIResourceUri;
55 import org.onap.so.client.aai.entities.uri.AAIUriFactory;
56 import org.onap.so.client.exception.BBObjectNotFoundException;
57 import org.onap.so.client.exception.ExceptionBuilder;
58 import org.onap.so.client.orchestration.AAIConfigurationResources;
59 import org.onap.so.client.orchestration.AAIInstanceGroupResources;
60 import org.onap.so.client.orchestration.AAINetworkResources;
61 import org.onap.so.client.orchestration.AAIServiceInstanceResources;
62 import org.onap.so.client.orchestration.AAIVfModuleResources;
63 import org.onap.so.client.orchestration.AAIVnfResources;
64 import org.onap.so.client.orchestration.AAIVolumeGroupResources;
65 import org.onap.so.client.orchestration.AAIVpnBindingResources;
66 import org.onap.so.logger.ErrorCode;
67 import org.onap.so.logger.MessageEnum;
68 import org.slf4j.Logger;
69 import org.slf4j.LoggerFactory;
70 import org.springframework.beans.factory.annotation.Autowired;
71 import org.springframework.core.env.Environment;
72 import org.springframework.stereotype.Component;
75 public class AAICreateTasks {
77 private static final Logger logger = LoggerFactory.getLogger(AAICreateTasks.class);
78 private static final String networkTypeProvider = "PROVIDER";
79 private static String NETWORK_COLLECTION_NAME = "networkCollectionName";
80 private static String CONTRAIL_NETWORK_POLICY_FQDN_LIST = "contrailNetworkPolicyFqdnList";
81 private static String HEAT_STACK_ID = "heatStackId";
82 private static String NETWORK_POLICY_FQDN_PARAM = "network-policy-fqdn";
84 private AAIServiceInstanceResources aaiSIResources;
86 private AAIVnfResources aaiVnfResources;
88 private ExceptionBuilder exceptionUtil;
90 private ExtractPojosForBB extractPojosForBB;
92 private AAIVolumeGroupResources aaiVolumeGroupResources;
94 private AAIVfModuleResources aaiVfModuleResources;
96 private AAINetworkResources aaiNetworkResources;
98 private AAIVpnBindingResources aaiVpnBindingResources;
100 private AAIConfigurationResources aaiConfigurationResources;
102 private AAIInstanceGroupResources aaiInstanceGroupResources;
104 private Environment env;
106 public void createServiceInstance(BuildingBlockExecution execution) {
108 ServiceInstance serviceInstance =
109 extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID);
110 Customer customer = execution.getGeneralBuildingBlock().getCustomer();
111 aaiSIResources.createServiceInstance(serviceInstance, customer);
112 } catch (Exception ex) {
113 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
117 public void createServiceSubscription(BuildingBlockExecution execution) {
119 ServiceInstance serviceInstance =
120 extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID);
121 Customer customer = execution.getGeneralBuildingBlock().getCustomer();
122 if (null == customer) {
123 String errorMessage =
124 "Exception in creating ServiceSubscription. Customer not present for ServiceInstanceID: "
125 + serviceInstance.getServiceInstanceId();
126 logger.error(Strings.repeat("{} ", 5), MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), errorMessage,
127 "BPMN", ErrorCode.UnknownError.getValue(), errorMessage);
128 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, errorMessage);
130 aaiSIResources.createServiceSubscription(customer);
131 } catch (BpmnError ex) {
133 } catch (Exception ex) {
134 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
138 public void createProject(BuildingBlockExecution execution) {
140 ServiceInstance serviceInstance =
141 extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID);
142 Project project = serviceInstance.getProject();
143 if (project != null) {
144 if (project.getProjectName() == null || "".equals(project.getProjectName())) {
145 logger.info("ProjectName is null in input. Skipping create project...");
147 aaiSIResources.createProjectandConnectServiceInstance(project, serviceInstance);
150 } catch (Exception ex) {
151 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
155 public void createOwningEntity(BuildingBlockExecution execution) {
157 ServiceInstance serviceInstance =
158 extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID);
159 OwningEntity owningEntity = serviceInstance.getOwningEntity();
160 String owningEntityId = owningEntity.getOwningEntityId();
161 String owningEntityName = owningEntity.getOwningEntityName();
162 if (owningEntityId == null || "".equals(owningEntityId)) {
163 String msg = "Exception in AAICreateOwningEntity. OwningEntityId is null.";
164 execution.setVariable("ErrorCreateOEAAI", msg);
165 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg);
167 if (aaiSIResources.existsOwningEntity(owningEntity)) {
168 aaiSIResources.connectOwningEntityandServiceInstance(owningEntity, serviceInstance);
170 if (owningEntityName == null || "".equals(owningEntityName)) {
172 "Exception in AAICreateOwningEntity. Can't create an owningEntity with no owningEntityName.";
173 logger.error(Strings.repeat("{} ", 5), MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(), msg,
174 "BPMN", ErrorCode.UnknownError.getValue(), msg);
175 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg);
177 if (aaiSIResources.existsOwningEntityName(owningEntityName)) {
179 "Exception in AAICreateOwningEntity. Can't create OwningEntity as name already exists in AAI associated with a different owning-entity-id (name must be unique)";
180 logger.error(Strings.repeat("{} ", 5), MessageEnum.BPMN_GENERAL_EXCEPTION_ARG.toString(),
181 msg, "BPMN", ErrorCode.UnknownError.getValue(), msg);
182 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, msg);
184 aaiSIResources.createOwningEntityandConnectServiceInstance(owningEntity, serviceInstance);
189 } catch (Exception ex) {
190 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
194 public void createVnf(BuildingBlockExecution execution) {
196 GenericVnf vnf = extractPojosForBB.extractByKey(execution, ResourceKey.GENERIC_VNF_ID);
197 ServiceInstance serviceInstance =
198 extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID);
199 execution.setVariable("homing", Boolean.TRUE.equals(vnf.isCallHoming()));
200 aaiVnfResources.createVnfandConnectServiceInstance(vnf, serviceInstance);
201 } catch (Exception ex) {
202 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
206 public void createPlatform(BuildingBlockExecution execution) {
208 GenericVnf vnf = extractPojosForBB.extractByKey(execution, ResourceKey.GENERIC_VNF_ID);
209 Platform platform = vnf.getPlatform();
210 if (platform != null) {
211 if (platform.getPlatformName() == null || "".equals(platform.getPlatformName())) {
212 logger.debug("PlatformName is null in input. Skipping create platform...");
214 List<String> platforms = splitCDL(platform.getPlatformName());
215 platforms.stream().forEach(platformName -> aaiVnfResources
216 .createPlatformandConnectVnf(new Platform(platformName), vnf));
219 } catch (Exception ex) {
220 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
225 public List<String> splitCDL(String str) {
226 return Stream.of(str.split(",")).map(String::trim).map(elem -> new String(elem)).collect(Collectors.toList());
229 public void createLineOfBusiness(BuildingBlockExecution execution) {
231 GenericVnf vnf = extractPojosForBB.extractByKey(execution, ResourceKey.GENERIC_VNF_ID);
232 LineOfBusiness lineOfBusiness = vnf.getLineOfBusiness();
233 if (lineOfBusiness != null) {
234 if (lineOfBusiness.getLineOfBusinessName() == null
235 || "".equals(lineOfBusiness.getLineOfBusinessName())) {
236 logger.info("lineOfBusiness is null in input. Skipping create lineOfBusiness...");
238 List<String> lineOfBussinesses = splitCDL(lineOfBusiness.getLineOfBusinessName());
239 lineOfBussinesses.stream().forEach(lobName -> aaiVnfResources
240 .createLineOfBusinessandConnectVnf(new LineOfBusiness(lobName), vnf));
243 } catch (Exception ex) {
244 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
248 public void createVolumeGroup(BuildingBlockExecution execution) {
250 GeneralBuildingBlock gBBInput = execution.getGeneralBuildingBlock();
252 GenericVnf genericVnf = extractPojosForBB.extractByKey(execution, ResourceKey.GENERIC_VNF_ID);
253 VolumeGroup volumeGroup = extractPojosForBB.extractByKey(execution, ResourceKey.VOLUME_GROUP_ID);
254 CloudRegion cloudRegion = gBBInput.getCloudRegion();
255 aaiVolumeGroupResources.createVolumeGroup(volumeGroup, cloudRegion);
256 aaiVolumeGroupResources.connectVolumeGroupToVnf(genericVnf, volumeGroup, cloudRegion);
257 aaiVolumeGroupResources.connectVolumeGroupToTenant(volumeGroup, cloudRegion);
258 } catch (Exception ex) {
259 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
263 public void createVfModule(BuildingBlockExecution execution) {
265 GenericVnf vnf = extractPojosForBB.extractByKey(execution, ResourceKey.GENERIC_VNF_ID);
266 VfModule vfModule = extractPojosForBB.extractByKey(execution, ResourceKey.VF_MODULE_ID);
268 if (vfModule.getModelInfoVfModule() != null
269 && !Boolean.TRUE.equals(vfModule.getModelInfoVfModule().getIsBaseBoolean())) {
270 moduleIndex = this.getLowestUnusedVfModuleIndexFromAAIVnfResponse(vnf, vfModule);
272 vfModule.setModuleIndex(moduleIndex);
273 aaiVfModuleResources.createVfModule(vfModule, vnf);
274 } catch (Exception ex) {
275 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
280 * BPMN access method to establish relationships in AAI
285 public void connectVfModuleToVolumeGroup(BuildingBlockExecution execution) {
287 GenericVnf vnf = extractPojosForBB.extractByKey(execution, ResourceKey.GENERIC_VNF_ID);
288 VfModule vfModule = extractPojosForBB.extractByKey(execution, ResourceKey.VF_MODULE_ID);
289 VolumeGroup volumeGroup = null;
291 volumeGroup = extractPojosForBB.extractByKey(execution, ResourceKey.VOLUME_GROUP_ID);
292 } catch (BBObjectNotFoundException e) {
293 logger.info("VolumeGroup not found. Skipping Connect between VfModule and VolumeGroup");
295 if (volumeGroup != null) {
296 aaiVfModuleResources.connectVfModuleToVolumeGroup(vnf, vfModule, volumeGroup,
297 execution.getGeneralBuildingBlock().getCloudRegion());
299 } catch (Exception ex) {
300 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
305 * BPMN access method to execute Create L3Network operation (PUT )in AAI
310 public void createNetwork(BuildingBlockExecution execution) {
312 ServiceInstance serviceInstance =
313 extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID);
314 L3Network l3network = extractPojosForBB.extractByKey(execution, ResourceKey.NETWORK_ID);
315 // set default to false. ToBe updated by SDNC
316 l3network.setIsBoundToVpn(false);
317 // define is bound to vpn flag as true if NEUTRON_NETWORK_TYPE is PROVIDER
318 if (l3network.getModelInfoNetwork().getNeutronNetworkType().equalsIgnoreCase(networkTypeProvider))
319 l3network.setIsBoundToVpn(true);
320 // put network shell in AAI
321 aaiNetworkResources.createNetworkConnectToServiceInstance(l3network, serviceInstance);
322 } catch (Exception ex) {
323 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
327 public void createCustomer(BuildingBlockExecution execution) throws Exception {
329 Customer customer = execution.getGeneralBuildingBlock().getCustomer();
331 aaiVpnBindingResources.createCustomer(customer);
332 } catch (Exception ex) {
333 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
338 * BPMN access method to execute NetworkCollection operation (PUT) in AAI
343 public void createNetworkCollection(BuildingBlockExecution execution) {
345 ServiceInstance serviceInstance =
346 extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID);
347 Collection networkCollection = serviceInstance.getCollection();
348 // pass name generated for NetworkCollection/NetworkCollectionInstanceGroup in previous step of the BB flow
350 networkCollection.setName(execution.getVariable(NETWORK_COLLECTION_NAME));
351 aaiNetworkResources.createNetworkCollection(networkCollection);
352 } catch (Exception ex) {
353 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
358 * BPMN access method to execute NetworkCollectionInstanceGroup operation (PUT) in AAI
363 public void createNetworkCollectionInstanceGroup(BuildingBlockExecution execution) {
365 ServiceInstance serviceInstance =
366 extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID);
367 InstanceGroup instanceGroup = serviceInstance.getCollection().getInstanceGroup();
368 // set name generated for NetworkCollection/NetworkCollectionInstanceGroup in previous step of the BB flow
369 instanceGroup.setInstanceGroupName(execution.getVariable(NETWORK_COLLECTION_NAME));
371 aaiNetworkResources.createNetworkInstanceGroup(instanceGroup);
372 } catch (Exception ex) {
373 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
379 * BPMN access method to establish relationships in AAI
384 public void connectNetworkToTenant(BuildingBlockExecution execution) {
386 L3Network l3network = extractPojosForBB.extractByKey(execution, ResourceKey.NETWORK_ID);
387 aaiNetworkResources.connectNetworkToTenant(l3network, execution.getGeneralBuildingBlock().getCloudRegion());
388 } catch (Exception ex) {
389 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
394 * BPMN access method to establish relationships in AAI
399 public void connectNetworkToCloudRegion(BuildingBlockExecution execution) {
401 L3Network l3network = extractPojosForBB.extractByKey(execution, ResourceKey.NETWORK_ID);
402 aaiNetworkResources.connectNetworkToCloudRegion(l3network,
403 execution.getGeneralBuildingBlock().getCloudRegion());
404 } catch (Exception ex) {
405 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
410 * BPMN access method to establish relationships in AAI
415 public void connectVnfToCloudRegion(BuildingBlockExecution execution) {
417 boolean cloudRegionsToSkip = false;
418 String[] cloudRegions = env.getProperty("mso.bpmn.cloudRegionIdsToSkipAddingVnfEdgesTo", String[].class);
419 if (cloudRegions != null) {
420 cloudRegionsToSkip = Arrays.stream(cloudRegions)
421 .anyMatch(execution.getGeneralBuildingBlock().getCloudRegion().getLcpCloudRegionId()::equals);
423 if (!cloudRegionsToSkip) {
424 GenericVnf vnf = extractPojosForBB.extractByKey(execution, ResourceKey.GENERIC_VNF_ID);
425 aaiVnfResources.connectVnfToCloudRegion(vnf, execution.getGeneralBuildingBlock().getCloudRegion());
427 } catch (Exception ex) {
428 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
433 * BPMN access method to establish relationships in AAI
438 public void connectVnfToTenant(BuildingBlockExecution execution) {
440 GenericVnf vnf = extractPojosForBB.extractByKey(execution, ResourceKey.GENERIC_VNF_ID);
441 aaiVnfResources.connectVnfToTenant(vnf, execution.getGeneralBuildingBlock().getCloudRegion());
442 } catch (Exception ex) {
443 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
448 * BPMN access method to establish relationships in AAI
453 public void connectNetworkToNetworkCollectionServiceInstance(BuildingBlockExecution execution) {
455 ServiceInstance serviceInstance =
456 extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID);
457 L3Network l3network = extractPojosForBB.extractByKey(execution, ResourceKey.NETWORK_ID);
458 aaiNetworkResources.connectNetworkToNetworkCollectionServiceInstance(l3network, serviceInstance);
459 } catch (Exception ex) {
460 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
465 * BPMN access method to establish relationships in AAI
470 public void connectNetworkToNetworkCollectionInstanceGroup(BuildingBlockExecution execution) {
472 ServiceInstance serviceInstance =
473 extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID);
474 L3Network l3network = extractPojosForBB.extractByKey(execution, ResourceKey.NETWORK_ID);
475 // connect network only if Instance Group / Collection objects exist
476 if (serviceInstance.getCollection() != null && serviceInstance.getCollection().getInstanceGroup() != null)
477 aaiNetworkResources.connectNetworkToNetworkCollectionInstanceGroup(l3network,
478 serviceInstance.getCollection().getInstanceGroup());
479 } catch (Exception ex) {
480 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
484 public void createConfiguration(BuildingBlockExecution execution) {
486 Configuration configuration = extractPojosForBB.extractByKey(execution, ResourceKey.CONFIGURATION_ID);
487 aaiConfigurationResources.createConfiguration(configuration);
488 } catch (Exception ex) {
489 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
493 public void createInstanceGroupVnf(BuildingBlockExecution execution) {
495 ServiceInstance serviceInstance =
496 extractPojosForBB.extractByKey(execution, ResourceKey.SERVICE_INSTANCE_ID);
497 InstanceGroup instanceGroup = extractPojosForBB.extractByKey(execution, ResourceKey.INSTANCE_GROUP_ID);
498 aaiInstanceGroupResources.createInstanceGroupandConnectServiceInstance(instanceGroup, serviceInstance);
499 } catch (Exception ex) {
500 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
504 public void createNetworkPolicies(BuildingBlockExecution execution) {
506 String fqdns = execution.getVariable(CONTRAIL_NETWORK_POLICY_FQDN_LIST);
507 if (fqdns != null && !fqdns.isEmpty()) {
508 String fqdnList[] = fqdns.split(",");
509 int fqdnCount = fqdnList.length;
511 for (int i = 0; i < fqdnCount; i++) {
512 String fqdn = fqdnList[i];
513 AAIResourceUri uri = AAIUriFactory.createResourceUri(AAIObjectPlurals.NETWORK_POLICY);
514 uri.queryParam(NETWORK_POLICY_FQDN_PARAM, fqdn);
515 Optional<org.onap.aai.domain.yang.NetworkPolicy> oNetPolicy =
516 aaiNetworkResources.getNetworkPolicy(uri);
517 if (!oNetPolicy.isPresent()) {
518 logger.debug("This network policy FQDN is not in AAI yet: {}", fqdn);
519 String networkPolicyId = UUID.randomUUID().toString();
520 logger.debug("Adding network-policy with network-policy-id {}", networkPolicyId);
521 NetworkPolicy networkPolicy = new NetworkPolicy();
522 networkPolicy.setNetworkPolicyId(networkPolicyId);
523 networkPolicy.setNetworkPolicyFqdn(fqdn);
524 networkPolicy.setHeatStackId(execution.getVariable(HEAT_STACK_ID));
526 aaiNetworkResources.createNetworkPolicy(networkPolicy);
531 } catch (Exception ex) {
532 exceptionUtil.buildAndThrowWorkflowException(execution, 7000, ex);
537 * Groups existing vf modules by the model uuid of our new vf module and returns the lowest unused index
539 * 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
540 * adding a new module type A, the vf-module-index should be 3 assuming contiguous indices (not 5, or 2)
543 protected int getLowestUnusedVfModuleIndexFromAAIVnfResponse(GenericVnf genericVnf, VfModule newVfModule) {
545 String newVfModuleModelInvariantUUID = null;
546 if (newVfModule.getModelInfoVfModule() != null) {
547 newVfModuleModelInvariantUUID = newVfModule.getModelInfoVfModule().getModelInvariantUUID();
551 if (genericVnf != null && genericVnf.getVfModules() != null && !genericVnf.getVfModules().isEmpty()) {
552 List<VfModule> modules = genericVnf.getVfModules().stream()
553 .filter(item -> !item.getVfModuleId().equals(newVfModule.getVfModuleId()))
554 .collect(Collectors.toList());
555 TreeSet<Integer> moduleIndices = new TreeSet<>();
556 int nullIndexFound = 0;
557 for (VfModule vfModule : modules) {
558 if (vfModule.getModelInfoVfModule() != null) {
559 if (vfModule.getModelInfoVfModule().getModelInvariantUUID().equals(newVfModuleModelInvariantUUID)) {
560 if (vfModule.getModuleIndex() != null) {
561 moduleIndices.add(vfModule.getModuleIndex());
564 logger.warn("Found null index for vf-module-id {} and model-invariant-uuid {}",
565 vfModule.getVfModuleId(), vfModule.getModelInfoVfModule().getModelInvariantUUID());
571 return calculateUnusedIndex(moduleIndices, nullIndexFound);
577 protected int calculateUnusedIndex(TreeSet<Integer> moduleIndices, int nullIndexFound) {
578 // pad array with nulls
579 Integer[] temp = new Integer[moduleIndices.size() + nullIndexFound];
580 Integer[] array = moduleIndices.toArray(temp);
582 // when a null is found skip that potential value
583 // effectively creates something like, [0,1,3,null,null] -> [0,1,null(2),3,null(4)]
584 for (int i = 0; i < array.length; i++, result++) {
585 if (Integer.valueOf(result) != array[i]) {
586 if (nullIndexFound > 0) {