2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
22 * Copyright (C) 2018 Bell Canada. All rights reserved.
24 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
25 * the License. You may obtain a copy of the License at
27 * http://www.apache.org/licenses/LICENSE-2.0
29 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
30 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
31 * specific language governing permissions and limitations under the License.
33 package org.onap.so.heatbridge;
35 import java.util.HashMap;
36 import java.util.List;
38 import java.util.Objects;
39 import java.util.Optional;
40 import java.util.concurrent.ConcurrentHashMap;
41 import java.util.function.Function;
42 import java.util.function.Predicate;
43 import java.util.stream.Collectors;
44 import javax.annotation.Nonnull;
45 import javax.ws.rs.NotFoundException;
46 import javax.ws.rs.WebApplicationException;
47 import org.apache.commons.collections.CollectionUtils;
48 import org.apache.commons.validator.routines.InetAddressValidator;
49 import org.onap.aai.domain.yang.Flavor;
50 import org.onap.aai.domain.yang.Image;
51 import org.onap.aai.domain.yang.L3InterfaceIpv4AddressList;
52 import org.onap.aai.domain.yang.L3InterfaceIpv6AddressList;
53 import org.onap.aai.domain.yang.L3Network;
54 import org.onap.aai.domain.yang.LInterface;
55 import org.onap.aai.domain.yang.PInterface;
56 import org.onap.aai.domain.yang.Pserver;
57 import org.onap.aai.domain.yang.Relationship;
58 import org.onap.aai.domain.yang.RelationshipList;
59 import org.onap.aai.domain.yang.SriovPf;
60 import org.onap.aai.domain.yang.SriovPfs;
61 import org.onap.aai.domain.yang.Subnets;
62 import org.onap.aai.domain.yang.SriovVf;
63 import org.onap.aai.domain.yang.SriovVfs;
64 import org.onap.aai.domain.yang.VfModule;
65 import org.onap.aai.domain.yang.Vlan;
66 import org.onap.aai.domain.yang.Vlans;
67 import org.onap.aai.domain.yang.Vserver;
68 import org.onap.aaiclient.client.aai.AAIObjectType;
69 import org.onap.aaiclient.client.aai.AAIResourcesClient;
70 import org.onap.aaiclient.client.aai.AAISingleTransactionClient;
71 import org.onap.aaiclient.client.aai.entities.AAIResultWrapper;
72 import org.onap.aaiclient.client.aai.entities.Relationships;
73 import org.onap.aaiclient.client.aai.entities.uri.AAIResourceUri;
74 import org.onap.aaiclient.client.aai.entities.uri.AAIUriFactory;
75 import org.onap.aaiclient.client.generated.fluentbuilders.AAIFluentTypeBuilder;
76 import org.onap.aaiclient.client.graphinventory.entities.uri.Depth;
77 import org.onap.aaiclient.client.graphinventory.exceptions.BulkProcessFailed;
78 import org.onap.logging.filter.base.ErrorCode;
79 import org.onap.so.db.catalog.beans.CloudIdentity;
80 import org.onap.so.db.catalog.beans.ServerType;
81 import org.onap.so.heatbridge.constants.HeatBridgeConstants;
82 import org.onap.so.heatbridge.factory.MsoCloudClientFactoryImpl;
83 import org.onap.so.heatbridge.helpers.AaiHelper;
84 import org.onap.so.heatbridge.openstack.api.OpenstackClient;
85 import org.onap.so.heatbridge.openstack.factory.OpenstackClientFactoryImpl;
86 import org.onap.so.heatbridge.utils.HeatBridgeUtils;
87 import org.onap.so.logger.LoggingAnchor;
88 import org.onap.so.logger.MessageEnum;
89 import org.onap.so.spring.SpringContextHelper;
90 import org.openstack4j.model.compute.Server;
91 import org.openstack4j.model.heat.Resource;
92 import org.openstack4j.model.network.IP;
93 import org.openstack4j.model.network.Network;
94 import org.openstack4j.model.network.NetworkType;
95 import org.openstack4j.model.network.Port;
96 import org.openstack4j.model.network.Subnet;
97 import org.slf4j.Logger;
98 import org.slf4j.LoggerFactory;
99 import org.springframework.core.env.Environment;
100 import com.google.common.base.Preconditions;
101 import com.google.common.base.Strings;
102 import com.google.common.collect.ImmutableMap;
103 import inet.ipaddr.IPAddressString;
106 * This class provides an implementation of {@link HeatBridgeApi}
108 public class HeatBridgeImpl implements HeatBridgeApi {
110 private static final Logger logger = LoggerFactory.getLogger(HeatBridgeImpl.class);
111 private static final String ERR_MSG_NULL_OS_CLIENT =
112 "Initialization error: Null openstack client. Authenticate with Keystone first.";
113 private static final String OOB_MGT_NETWORK_IDENTIFIER = "Management";
114 private OpenstackClient osClient;
115 private AAIResourcesClient resourcesClient;
116 private AAISingleTransactionClient transaction;
117 private String cloudOwner;
118 private String cloudRegionId;
119 private String regionId;
120 private String tenantId;
121 private AaiHelper aaiHelper = new AaiHelper();
122 private CloudIdentity cloudIdentity;
123 private Environment env;
126 public HeatBridgeImpl(AAIResourcesClient resourcesClient, final CloudIdentity cloudIdentity,
127 @Nonnull final String cloudOwner, @Nonnull final String cloudRegionId, @Nonnull final String regionId,
128 @Nonnull final String tenantId) {
129 Objects.requireNonNull(cloudOwner, "Null cloud-owner value!");
130 Objects.requireNonNull(cloudRegionId, "Null cloud-region identifier!");
131 Objects.requireNonNull(tenantId, "Null tenant identifier!");
132 Objects.requireNonNull(regionId, "Null regionId identifier!");
134 this.cloudIdentity = cloudIdentity;
135 this.cloudOwner = cloudOwner;
136 this.cloudRegionId = cloudRegionId;
137 this.regionId = regionId;
138 this.tenantId = tenantId;
139 this.resourcesClient = resourcesClient;
140 if (resourcesClient != null)
141 this.transaction = resourcesClient.beginSingleTransaction();
142 if (SpringContextHelper.getAppContext() != null)
143 this.env = SpringContextHelper.getAppContext().getEnvironment();
146 public HeatBridgeImpl() {
147 this.resourcesClient = new AAIResourcesClient();
148 this.transaction = resourcesClient.beginSingleTransaction();
152 public OpenstackClient authenticate() throws HeatBridgeException {
153 String keystoneVersion = "";
154 if (ServerType.KEYSTONE.equals(cloudIdentity.getIdentityServerType()))
155 keystoneVersion = "v2.0";
156 else if (ServerType.KEYSTONE_V3.equals(cloudIdentity.getIdentityServerType())) {
157 keystoneVersion = "v3";
159 keystoneVersion = "UNKNOWN";
161 logger.trace("Keystone Version: {} ", keystoneVersion);
162 this.osClient = new MsoCloudClientFactoryImpl(new OpenstackClientFactoryImpl()).getOpenstackClient(
163 cloudIdentity.getIdentityUrl(), cloudIdentity.getMsoId(), cloudIdentity.getMsoPass(), regionId,
164 tenantId, keystoneVersion, cloudIdentity.getUserDomainName(), cloudIdentity.getProjectDomainName());
165 logger.trace("Successfully authenticated with keystone for tenant: {} and region: {}", tenantId, regionId);
170 public List<Resource> queryNestedHeatStackResources(final String heatStackId) {
171 Objects.requireNonNull(osClient, ERR_MSG_NULL_OS_CLIENT);
172 Preconditions.checkState(!Strings.isNullOrEmpty(heatStackId), "Invalid heatStackId!");
173 List<Resource> stackBasedResources =
174 osClient.getStackBasedResources(heatStackId, HeatBridgeConstants.OS_DEFAULT_HEAT_NESTING);
175 logger.debug(stackBasedResources.size() + " heat stack resources are extracted for stack: " + heatStackId);
176 return stackBasedResources;
180 public List<String> extractStackResourceIdsByResourceType(final List<Resource> stackResources,
181 final String resourceType) {
182 return stackResources.stream().filter(stackResource -> stackResource.getType().equals(resourceType))
183 .map(Resource::getPhysicalResourceId).collect(Collectors.toList());
187 public List<String> extractNetworkIds(final List<String> networkNameList) {
188 Objects.requireNonNull(osClient, ERR_MSG_NULL_OS_CLIENT);
189 return networkNameList.stream()
190 .map(netName -> osClient
191 .listNetworksByFilter(ImmutableMap.of(HeatBridgeConstants.OS_NAME_KEY, netName)))
192 .filter(nets -> nets != null && nets.size() == 1) // extract network-id only if network-name is unique
193 .map(nets -> nets.get(0).getId()).collect(Collectors.toList());
197 public List<Server> getAllOpenstackServers(final List<Resource> stackResources) {
198 Objects.requireNonNull(osClient, ERR_MSG_NULL_OS_CLIENT);
199 // Filter Openstack Compute resources
200 List<String> serverIds =
201 extractStackResourceIdsByResourceType(stackResources, HeatBridgeConstants.OS_SERVER_RESOURCE_TYPE);
202 return serverIds.stream().map(serverId -> osClient.getServerById(serverId)).collect(Collectors.toList());
206 public List<Network> getAllOpenstackProviderNetworks(final List<Resource> stackResources) {
207 Objects.requireNonNull(osClient, ERR_MSG_NULL_OS_CLIENT);
208 // Filter Openstack Compute resources
209 List<String> providerNetworkIds =
210 extractStackResourceIdsByResourceType(stackResources, HeatBridgeConstants.OS_NEUTRON_PROVIDERNET);
211 return providerNetworkIds.stream().map(providerNetworkId -> osClient.getNetworkById(providerNetworkId))
212 .collect(Collectors.toList());
216 public List<org.openstack4j.model.compute.Image> extractOpenstackImagesFromServers(final List<Server> servers) {
217 Objects.requireNonNull(osClient, ERR_MSG_NULL_OS_CLIENT);
218 return servers.stream().map(Server::getImage)
219 .filter(distinctByProperty(org.openstack4j.model.compute.Image::getId)).collect(Collectors.toList());
223 public List<org.openstack4j.model.compute.Flavor> extractOpenstackFlavorsFromServers(final List<Server> servers) {
224 Objects.requireNonNull(osClient, ERR_MSG_NULL_OS_CLIENT);
225 return servers.stream().map(Server::getFlavor)
226 .filter(distinctByProperty(org.openstack4j.model.compute.Flavor::getId)).collect(Collectors.toList());
229 public void buildAddNetworksToAaiAction(final String genericVnfId, final String vfModuleId,
230 List<Network> networks) {
231 networks.forEach(network -> {
232 L3Network l3Network = aaiHelper.buildNetwork(network);
233 if (l3Network != null) {
234 l3Network.setSubnets(buildSunets(network));
236 RelationshipList relationshipList = new RelationshipList();
237 List<Relationship> relationships = relationshipList.getRelationship();
239 relationships.add(aaiHelper.getRelationshipToVfModule(genericVnfId, vfModuleId));
240 relationships.add(aaiHelper.getRelationshipToTenant(cloudOwner, cloudRegionId, tenantId));
242 l3Network.setRelationshipList(relationshipList);
243 transaction.createIfNotExists(
244 AAIUriFactory.createResourceUri(AAIObjectType.L3_NETWORK, l3Network.getNetworkId()),
245 Optional.of(l3Network));
251 public void buildAddImagesToAaiAction(final List<org.openstack4j.model.compute.Image> images)
252 throws HeatBridgeException {
253 for (org.openstack4j.model.compute.Image image : images) {
254 Image aaiImage = aaiHelper.buildImage(image);
256 AAIResourceUri uri = AAIUriFactory.createResourceUri(AAIObjectType.IMAGE, cloudOwner, cloudRegionId,
257 aaiImage.getImageId());
258 if (!resourcesClient.exists(uri)) {
259 transaction.create(uri, aaiImage);
260 logger.debug("Queuing AAI command to add image: " + aaiImage.getImageId());
262 logger.debug("Nothing to add since image: " + aaiImage.getImageId() + "already exists in AAI.");
264 } catch (WebApplicationException e) {
265 throw new HeatBridgeException(
266 "Failed to update image to AAI: " + aaiImage.getImageId() + ". Error" + " cause: " + e, e);
272 public void buildAddFlavorsToAaiAction(final List<org.openstack4j.model.compute.Flavor> flavors)
273 throws HeatBridgeException {
274 for (org.openstack4j.model.compute.Flavor flavor : flavors) {
275 Flavor aaiFlavor = aaiHelper.buildFlavor(flavor);
277 AAIResourceUri uri = AAIUriFactory.createResourceUri(AAIObjectType.FLAVOR, cloudOwner, cloudRegionId,
278 aaiFlavor.getFlavorId());
279 transaction.createIfNotExists(uri, Optional.of(aaiFlavor));
280 } catch (WebApplicationException e) {
281 throw new HeatBridgeException(
282 "Failed to update flavor to AAI: " + aaiFlavor.getFlavorId() + ". Error" + " cause: " + e, e);
288 public void buildAddVserversToAaiAction(final String genericVnfId, final String vfModuleId,
289 final List<Server> servers) {
290 servers.forEach(server -> {
291 Vserver vserver = aaiHelper.buildVserver(server.getId(), server);
293 // Build vserver relationships to: image, flavor, pserver, vf-module
294 vserver.setRelationshipList(
295 aaiHelper.getVserverRelationshipList(cloudOwner, cloudRegionId, genericVnfId, vfModuleId, server));
296 transaction.createIfNotExists(AAIUriFactory.createResourceUri(AAIObjectType.VSERVER, cloudOwner,
297 cloudRegionId, tenantId, vserver.getVserverId()), Optional.of(vserver));
302 public void buildAddVserverLInterfacesToAaiAction(final List<Resource> stackResources,
303 final List<String> oobMgtNetIds, String cloudOwner) {
304 Objects.requireNonNull(osClient, ERR_MSG_NULL_OS_CLIENT);
305 List<String> portIds =
306 extractStackResourceIdsByResourceType(stackResources, HeatBridgeConstants.OS_PORT_RESOURCE_TYPE);
309 for (String portId : portIds) {
310 Port port = osClient.getPortById(portId);
311 Network network = osClient.getNetworkById(port.getNetworkId());
312 LInterface lIf = new LInterface();
313 lIf.setInterfaceId(port.getId());
314 lIf.setInterfaceName(port.getName());
315 lIf.setMacaddr(port.getMacAddress());
316 lIf.setNetworkName(network.getName());
317 lIf.setIsPortMirrored(false);
318 lIf.setIsIpUnnumbered(false);
319 lIf.setInMaint(false);
320 if (oobMgtNetIds != null && oobMgtNetIds.contains(port.getNetworkId())) {
321 lIf.setInterfaceRole(OOB_MGT_NETWORK_IDENTIFIER);
323 lIf.setInterfaceRole(port.getvNicType());
325 boolean isL2Multicast = false;
326 if (port.getProfile() != null && port.getProfile().get("trusted") != null) {
327 String trusted = port.getProfile().get("trusted").toString();
328 if (Boolean.parseBoolean(trusted)) {
329 isL2Multicast = true;
332 lIf.setL2Multicasting(isL2Multicast);
334 transaction.createIfNotExists(AAIUriFactory.createResourceUri(AAIObjectType.L_INTERFACE, cloudOwner,
335 cloudRegionId, tenantId, port.getDeviceId(), lIf.getInterfaceName()), Optional.of(lIf));
337 updateLInterfaceIps(port, lIf);
338 if (cloudOwner.equals(env.getProperty("mso.cloudOwner.included", ""))) {
339 updateLInterfaceVlan(port, lIf);
342 updateSriovPfToPserver(port, lIf);
347 public void createPserversAndPinterfacesIfNotPresentInAai(final List<Resource> stackResources)
348 throws HeatBridgeException {
349 if (stackResources == null) {
352 Map<String, Pserver> serverHostnames = getPserverMapping(stackResources);
353 createPServerIfNotExists(serverHostnames);
354 List<String> portIds =
355 extractStackResourceIdsByResourceType(stackResources, HeatBridgeConstants.OS_PORT_RESOURCE_TYPE);
356 for (String portId : portIds) {
357 Port port = osClient.getPortById(portId);
358 if (port.getvNicType().equalsIgnoreCase(HeatBridgeConstants.OS_SRIOV_PORT_TYPE)) {
359 createPServerPInterfaceIfNotExists(serverHostnames.get(port.getHostId()).getHostname(),
360 aaiHelper.buildPInterface(port));
365 private Map<String, Pserver> getPserverMapping(final List<Resource> stackResources) {
366 List<Server> osServers = getAllOpenstackServers(stackResources);
367 Map<String, Pserver> pserverMap = new HashMap<>();
368 if (osServers != null) {
369 for (Server server : osServers) {
370 Pserver pserver = aaiHelper.buildPserver(server);
371 if (pserver != null) {
372 pserverMap.put(server.getHost(), pserver);
379 private Subnets buildSunets(Network network) {
380 Subnets aaiSubnets = new Subnets();
381 List<String> subnetIds = network.getSubnets();
383 subnetIds.forEach(subnetId -> {
384 Subnet subnet = osClient.getSubnetById(subnetId);
385 org.onap.aai.domain.yang.Subnet aaiSubnet = aaiHelper.buildSubnet(subnet);
386 if (aaiSubnet != null) {
387 aaiSubnets.getSubnet().add(aaiSubnet);
393 private void createPServerIfNotExists(Map<String, Pserver> serverHostnames) {
394 for (Pserver pserver : serverHostnames.values()) {
395 AAIResourceUri uri = AAIUriFactory.createResourceUri(AAIObjectType.PSERVER, pserver.getHostname());
396 resourcesClient.createIfNotExists(uri, Optional.of(pserver));
400 private void createPServerPInterfaceIfNotExists(String pserverHostname, PInterface pInterface) {
401 AAIResourceUri uri = AAIUriFactory.createResourceUri(AAIObjectType.P_INTERFACE, pserverHostname,
402 pInterface.getInterfaceName());
403 resourcesClient.createIfNotExists(uri, Optional.of(pInterface));
406 private void updateLInterfaceVlan(final Port port, final LInterface lIf) {
407 Vlan vlan = new Vlan();
408 Network network = osClient.getNetworkById(port.getNetworkId());
409 if (network.getNetworkType() != null && network.getNetworkType().equals(NetworkType.VLAN)) {
410 vlan.setVlanInterface(port.getName() + network.getProviderSegID());
411 vlan.setVlanIdOuter(Long.parseLong(network.getProviderSegID()));
412 vlan.setVlanIdInner(0L);
413 vlan.setInMaint(false);
414 vlan.setIsIpUnnumbered(false);
415 vlan.setIsPrivate(false);
419 AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.cloudInfrastructure()
420 .cloudRegion(cloudOwner, cloudRegionId).tenant(tenantId).vserver(port.getDeviceId())
421 .lInterface(lIf.getInterfaceName()).vlan(vlan.getVlanInterface())),
425 if (port.getvNicType() != null && port.getvNicType().equalsIgnoreCase(HeatBridgeConstants.OS_SRIOV_PORT_TYPE)) {
426 SriovVf sriovVf = new SriovVf();
427 sriovVf.setPciId(port.getProfile().get(HeatBridgeConstants.OS_PCI_SLOT_KEY).toString());
428 sriovVf.setNeutronNetworkId(port.getNetworkId());
429 sriovVf.setVfVlanFilter("0");
430 sriovVf.setVfVlanAntiSpoofCheck(false);
431 sriovVf.setVfMacAntiSpoofCheck(false);
435 AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.cloudInfrastructure()
436 .cloudRegion(cloudOwner, cloudRegionId).tenant(tenantId).vserver(port.getDeviceId())
437 .lInterface(lIf.getInterfaceName()).sriovVf(sriovVf.getPciId())),
438 Optional.of(sriovVf));
443 * Needs to be corrected according to the specification that is in draft If pserver/p-interface does not have a
444 * SRIOV-PF object matching the PCI-ID of the Openstack port object, then create it in AAI. Openstack SRIOV Port
445 * object has pci-id (to match sriov-pf on pserver/p-interface), physical-network ID (that matches the p-interface
448 * @param port Openstack port object
449 * @param lIf AAI l-interface object
451 private void updateSriovPfToPserver(final Port port, final LInterface lIf) {
452 if (port.getvNicType().equalsIgnoreCase(HeatBridgeConstants.OS_SRIOV_PORT_TYPE)) {
453 if (port.getProfile() == null || Strings
454 .isNullOrEmpty(port.getProfile().get(HeatBridgeConstants.OS_PHYSICAL_NETWORK_KEY).toString())) {
455 logger.debug("The SRIOV port:" + port.getName() + " is missing physical-network-id, cannot update "
456 + "sriov-pf object for host pserver: " + port.getHostId());
459 Optional<String> matchingPifName = HeatBridgeUtils.getMatchingPserverPifName(
460 port.getProfile().get(HeatBridgeConstants.OS_PHYSICAL_NETWORK_KEY).toString());
461 if (matchingPifName.isPresent()) {
462 // Update l-interface description
463 String pserverHostName = port.getHostId();
464 lIf.setInterfaceDescription(
465 "Attached to SR-IOV port: " + pserverHostName + "::" + matchingPifName.get());
467 Optional<PInterface> matchingPIf = resourcesClient.get(PInterface.class, AAIUriFactory
468 .createResourceUri(AAIObjectType.P_INTERFACE, pserverHostName, matchingPifName.get())
470 if (matchingPIf.isPresent()) {
471 SriovPfs pIfSriovPfs = matchingPIf.get().getSriovPfs();
472 if (pIfSriovPfs == null) {
473 pIfSriovPfs = new SriovPfs();
475 // Extract PCI-ID from OS port object
476 String pfPciId = port.getProfile().get(HeatBridgeConstants.OS_PCI_SLOT_KEY).toString();
478 List<SriovPf> existingSriovPfs = pIfSriovPfs.getSriovPf();
479 if (CollectionUtils.isEmpty(existingSriovPfs) || existingSriovPfs.stream()
480 .noneMatch(existingSriovPf -> existingSriovPf.getPfPciId().equals(pfPciId))) {
481 // Add sriov-pf object with PCI-ID to AAI
482 SriovPf sriovPf = new SriovPf();
483 sriovPf.setPfPciId(pfPciId);
484 logger.debug("Queuing AAI command to update sriov-pf object to pserver: " + pserverHostName
485 + "/" + matchingPifName.get());
487 AAIResourceUri sriovPfUri = AAIUriFactory.createResourceUri(AAIObjectType.SRIOV_PF,
488 pserverHostName, matchingPifName.get(), sriovPf.getPfPciId());
490 if (!resourcesClient.exists(sriovPfUri)) {
491 transaction.create(sriovPfUri, sriovPf);
493 AAIResourceUri sriovVfUri = AAIUriFactory.createResourceUri(AAIObjectType.SRIOV_VF,
494 cloudOwner, cloudRegionId, tenantId, port.getDeviceId(), lIf.getInterfaceName(),
495 port.getProfile().get(HeatBridgeConstants.OS_PCI_SLOT_KEY).toString());
497 transaction.connect(sriovPfUri, sriovVfUri);
501 } catch (WebApplicationException e) {
502 // Silently log that we failed to update the Pserver p-interface with PCI-ID
503 logger.error(LoggingAnchor.NINE, MessageEnum.GENERAL_EXCEPTION, pserverHostName,
504 matchingPifName.get(), cloudOwner, tenantId, "OpenStack", "Heatbridge",
505 ErrorCode.DataError.getValue(), "Exception - Failed to add sriov-pf object to pserver", e);
511 private void updateLInterfaceIps(final Port port, final LInterface lIf) {
512 for (IP ip : port.getFixedIps()) {
513 String ipAddress = ip.getIpAddress();
514 if (InetAddressValidator.getInstance().isValidInet4Address(ipAddress)) {
515 Subnet subnet = osClient.getSubnetById(ip.getSubnetId());
516 IPAddressString cidr = new IPAddressString(subnet.getCidr());
517 L3InterfaceIpv4AddressList lInterfaceIp = new L3InterfaceIpv4AddressList();
518 lInterfaceIp.setL3InterfaceIpv4Address(ipAddress);
519 lInterfaceIp.setNeutronNetworkId(port.getNetworkId());
520 lInterfaceIp.setNeutronSubnetId(ip.getSubnetId());
521 lInterfaceIp.setL3InterfaceIpv4PrefixLength(Long.parseLong(cidr.getNetworkPrefixLength().toString()));
523 transaction.createIfNotExists(
524 AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.cloudInfrastructure()
525 .cloudRegion(cloudOwner, cloudRegionId).tenant(tenantId).vserver(port.getDeviceId())
526 .lInterface(lIf.getInterfaceName()).l3InterfaceIpv4AddressList(ipAddress)),
527 Optional.of(lInterfaceIp));
528 } else if (InetAddressValidator.getInstance().isValidInet6Address(ipAddress)) {
529 Subnet subnet = osClient.getSubnetById(ip.getSubnetId());
530 IPAddressString cidr = new IPAddressString(subnet.getCidr());
531 L3InterfaceIpv6AddressList ipv6 = new L3InterfaceIpv6AddressList();
532 ipv6.setL3InterfaceIpv6Address(ipAddress);
533 ipv6.setNeutronNetworkId(port.getNetworkId());
534 ipv6.setNeutronSubnetId(ip.getSubnetId());
535 ipv6.setL3InterfaceIpv6PrefixLength(Long.parseLong(cidr.getNetworkPrefixLength().toString()));
537 transaction.createIfNotExists(
538 AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.cloudInfrastructure()
539 .cloudRegion(cloudOwner, cloudRegionId).tenant(tenantId).vserver(port.getDeviceId())
540 .lInterface(lIf.getInterfaceName()).l3InterfaceIpv6AddressList(ipAddress)),
547 public void submitToAai(boolean dryrun) throws HeatBridgeException {
549 transaction.execute(dryrun);
550 } catch (BulkProcessFailed e) {
551 String msg = "Failed to commit transaction";
552 logger.debug(msg + " with error: " + e);
553 throw new HeatBridgeException(msg, e);
558 public void deleteVfModuleData(@Nonnull final String vnfId, @Nonnull final String vfModuleId)
559 throws HeatBridgeException {
560 Objects.requireNonNull(vnfId, "Null vnf-id!");
561 Objects.requireNonNull(vfModuleId, "Null vf-module-id!");
563 Optional<VfModule> vfModule = resourcesClient
564 .get(AAIUriFactory.createResourceUri(AAIObjectType.VF_MODULE, vnfId, vfModuleId).depth(Depth.ONE),
565 NotFoundException.class)
566 .asBean(VfModule.class);
568 AAIResultWrapper resultWrapper = new AAIResultWrapper(vfModule.get());
569 Optional<Relationships> relationships = resultWrapper.getRelationships();
570 logger.debug("VfModule contains relationships in AAI: {}", relationships.isPresent());
571 if (relationships.isPresent()) {
573 List<AAIResourceUri> l3NetworkUris = relationships.get().getRelatedUris(AAIObjectType.L3_NETWORK);
574 logger.debug("L3Network contains {} relationships in AAI", l3NetworkUris.size());
576 if (!l3NetworkUris.isEmpty()) {
577 for (AAIResourceUri l3NetworkUri : l3NetworkUris) {
578 if (env.getProperty("heatBridgeDryrun", Boolean.class, true)) {
579 logger.debug("Would delete L3Network: {}", l3NetworkUri.build().toString());
581 resourcesClient.delete(l3NetworkUri);
586 List<AAIResourceUri> vserverUris = relationships.get().getRelatedUris(AAIObjectType.VSERVER);
587 logger.debug("VServer contains {} relationships in AAI", vserverUris.size());
588 createTransactionToDeleteSriovPfFromPserver(vserverUris);
590 if (!vserverUris.isEmpty()) {
591 for (AAIResourceUri vserverUri : vserverUris) {
592 if (env.getProperty("heatBridgeDryrun", Boolean.class, true)) {
593 logger.debug("Would delete Vserver: {}", vserverUri.build().toString());
595 resourcesClient.delete(vserverUri);
601 } catch (NotFoundException e) {
602 String msg = "Failed to commit delete heatbridge data transaction";
603 logger.debug(msg + " with error: " + e);
604 throw new HeatBridgeException(msg, e);
605 } catch (Exception e) {
606 String msg = "Failed to commit delete heatbridge data transaction";
607 logger.debug(msg + " with error: " + e);
608 throw new HeatBridgeException(msg, e);
612 private void createTransactionToDeleteSriovPfFromPserver(List<AAIResourceUri> vserverUris) {
613 Map<String, List<String>> pserverToPciIdMap = getPserverToPciIdMap(vserverUris);
614 for (Map.Entry<String, List<String>> entry : pserverToPciIdMap.entrySet()) {
615 String pserverName = entry.getKey();
616 List<String> pciIds = entry.getValue();
617 Optional<Pserver> pserver = resourcesClient.get(Pserver.class,
618 AAIUriFactory.createResourceUri(AAIObjectType.PSERVER, pserverName).depth(Depth.TWO));
619 if (pserver.isPresent()) {
620 // For each pserver/p-interface match sriov-vfs by pic-id and delete them.
621 pserver.get().getPInterfaces().getPInterface().stream().filter(
622 pIf -> pIf.getSriovPfs() != null && CollectionUtils.isNotEmpty(pIf.getSriovPfs().getSriovPf()))
623 .forEach(pIf -> pIf.getSriovPfs().getSriovPf().forEach(sriovPf -> {
624 if (pciIds.contains(sriovPf.getPfPciId())) {
625 logger.debug("creating transaction to delete SR-IOV PF: " + pIf.getInterfaceName()
626 + " from PServer: " + pserverName);
627 if (env.getProperty("heatBridgeDryrun", Boolean.class, true)) {
628 logger.debug("Would delete Sriov Pf: {}",
630 .createResourceUri(AAIObjectType.SRIOV_PF, pserverName,
631 pIf.getInterfaceName(), sriovPf.getPfPciId())
632 .build().toString());
634 resourcesClient.delete(AAIUriFactory.createResourceUri(AAIObjectType.SRIOV_PF,
635 pserverName, pIf.getInterfaceName(), sriovPf.getPfPciId()));
643 private Map<String, List<String>> getPserverToPciIdMap(List<AAIResourceUri> vserverUris) {
644 Map<String, List<String>> pserverToPciIdMap = new HashMap<>();
645 for (AAIResourceUri vserverUri : vserverUris) {
646 AAIResultWrapper vserverWrapper = resourcesClient.get(vserverUri.depth(Depth.TWO));
647 Optional<Relationships> vserverRelationships = vserverWrapper.getRelationships();
648 if (vserverRelationships.isPresent()
649 && CollectionUtils.isNotEmpty(vserverRelationships.get().getRelatedLinks(AAIObjectType.PSERVER))) {
650 Vserver vserver = vserverWrapper.asBean(Vserver.class).get();
651 List<String> pciIds = HeatBridgeUtils.extractPciIdsFromVServer(vserver);
652 if (CollectionUtils.isNotEmpty(pciIds)) {
653 List<AAIResourceUri> matchingPservers =
654 vserverRelationships.get().getRelatedUris(AAIObjectType.PSERVER);
655 if (matchingPservers != null && matchingPservers.size() == 1) {
656 pserverToPciIdMap.put(matchingPservers.get(0).getURIKeys().get("hostname"), pciIds);
661 return pserverToPciIdMap;
664 private <T> Predicate<T> distinctByProperty(Function<? super T, Object> keyExtractor) {
665 Map<Object, Boolean> map = new ConcurrentHashMap<>();
666 return t -> map.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;