X-Git-Url: https://gerrit.onap.org/r/gitweb?a=blobdiff_plain;f=adapters%2Fmso-openstack-adapters%2Fsrc%2Fmain%2Fjava%2Forg%2Fonap%2Fso%2Fheatbridge%2FHeatBridgeImpl.java;h=dbd56c52bdc22d7048a0e07b53c96c7dd359a03d;hb=153778a1ae7ee07f4730493d11f3ca72e07bce08;hp=dcf33da128532c734dd7df90ca9b3e42bdbf5941;hpb=5e67cc099f6bcade2f12bf9220bdf3682f2d06c1;p=so.git diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/heatbridge/HeatBridgeImpl.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/heatbridge/HeatBridgeImpl.java index dcf33da128..dbd56c52bd 100644 --- a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/heatbridge/HeatBridgeImpl.java +++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/heatbridge/HeatBridgeImpl.java @@ -32,6 +32,8 @@ */ package org.onap.so.heatbridge; +import java.io.IOException; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -42,33 +44,49 @@ import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Collectors; import javax.annotation.Nonnull; +import javax.ws.rs.NotFoundException; import javax.ws.rs.WebApplicationException; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.validator.routines.InetAddressValidator; import org.onap.aai.domain.yang.Flavor; import org.onap.aai.domain.yang.Image; import org.onap.aai.domain.yang.L3InterfaceIpv4AddressList; +import org.onap.aai.domain.yang.L3InterfaceIpv6AddressList; +import org.onap.aai.domain.yang.L3Network; import org.onap.aai.domain.yang.LInterface; import org.onap.aai.domain.yang.PInterface; import org.onap.aai.domain.yang.Pserver; +import org.onap.aai.domain.yang.Relationship; +import org.onap.aai.domain.yang.RelationshipList; import org.onap.aai.domain.yang.SriovPf; import org.onap.aai.domain.yang.SriovPfs; +import org.onap.aai.domain.yang.Subnets; import org.onap.aai.domain.yang.SriovVf; -import org.onap.aai.domain.yang.SriovVfs; import org.onap.aai.domain.yang.VfModule; import org.onap.aai.domain.yang.Vlan; -import org.onap.aai.domain.yang.Vlans; import org.onap.aai.domain.yang.Vserver; -import org.onap.logging.filter.base.ErrorCode; -import org.onap.aaiclient.client.aai.AAIObjectType; +import org.onap.aaiclient.client.aai.AAIDSLQueryClient; import org.onap.aaiclient.client.aai.AAIResourcesClient; import org.onap.aaiclient.client.aai.AAISingleTransactionClient; import org.onap.aaiclient.client.aai.entities.AAIResultWrapper; import org.onap.aaiclient.client.aai.entities.Relationships; +import org.onap.aaiclient.client.aai.entities.Results; import org.onap.aaiclient.client.aai.entities.uri.AAIResourceUri; import org.onap.aaiclient.client.aai.entities.uri.AAIUriFactory; +import org.onap.aaiclient.client.generated.fluentbuilders.AAIFluentTypeBuilder; +import org.onap.aaiclient.client.generated.fluentbuilders.AAIFluentTypeBuilder.Types; +import org.onap.aaiclient.client.graphinventory.Format; +import org.onap.aaiclient.client.graphinventory.entities.DSLQuery; +import org.onap.aaiclient.client.graphinventory.entities.DSLQueryBuilder; +import org.onap.aaiclient.client.graphinventory.entities.DSLStartNode; +import org.onap.aaiclient.client.graphinventory.entities.Node; +import org.onap.aaiclient.client.graphinventory.entities.Start; +import org.onap.aaiclient.client.graphinventory.entities.TraversalBuilder; +import org.onap.aaiclient.client.graphinventory.entities.__; import org.onap.aaiclient.client.graphinventory.entities.uri.Depth; import org.onap.aaiclient.client.graphinventory.exceptions.BulkProcessFailed; +import org.onap.logging.filter.base.ErrorCode; +import org.onap.so.cloud.resource.beans.NodeType; import org.onap.so.db.catalog.beans.CloudIdentity; import org.onap.so.db.catalog.beans.ServerType; import org.onap.so.heatbridge.constants.HeatBridgeConstants; @@ -79,17 +97,23 @@ import org.onap.so.heatbridge.openstack.factory.OpenstackClientFactoryImpl; import org.onap.so.heatbridge.utils.HeatBridgeUtils; import org.onap.so.logger.LoggingAnchor; import org.onap.so.logger.MessageEnum; +import org.onap.so.spring.SpringContextHelper; import org.openstack4j.model.compute.Server; import org.openstack4j.model.heat.Resource; import org.openstack4j.model.network.IP; import org.openstack4j.model.network.Network; import org.openstack4j.model.network.NetworkType; import org.openstack4j.model.network.Port; +import org.openstack4j.model.network.Subnet; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.core.env.Environment; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.base.Preconditions; import com.google.common.base.Strings; import com.google.common.collect.ImmutableMap; +import inet.ipaddr.IPAddressString; /** * This class provides an implementation of {@link HeatBridgeApi} @@ -100,19 +124,34 @@ public class HeatBridgeImpl implements HeatBridgeApi { private static final String ERR_MSG_NULL_OS_CLIENT = "Initialization error: Null openstack client. Authenticate with Keystone first."; private static final String OOB_MGT_NETWORK_IDENTIFIER = "Management"; + + protected static final String DIRECT = "direct"; + protected static final String PCI_SLOT = "pci_slot"; + protected static final String OVSNET = "ovsnet"; + protected static final String SRIOV = "SRIOV"; + protected static final String RESOURCE_LINK = "resource-link"; + + protected static final Object PRIVATE_VLANS = "private_vlans"; + protected static final Object PUBLIC_VLANS = "public_vlans"; + + protected ObjectMapper mapper = new ObjectMapper(); + private OpenstackClient osClient; private AAIResourcesClient resourcesClient; + private AAIDSLQueryClient aaiDSLClient; private AAISingleTransactionClient transaction; private String cloudOwner; private String cloudRegionId; private String regionId; private String tenantId; + private NodeType nodeType; private AaiHelper aaiHelper = new AaiHelper(); private CloudIdentity cloudIdentity; + private Environment env; public HeatBridgeImpl(AAIResourcesClient resourcesClient, final CloudIdentity cloudIdentity, @Nonnull final String cloudOwner, @Nonnull final String cloudRegionId, @Nonnull final String regionId, - @Nonnull final String tenantId) { + @Nonnull final String tenantId, @Nonnull final NodeType nodeType) { Objects.requireNonNull(cloudOwner, "Null cloud-owner value!"); Objects.requireNonNull(cloudRegionId, "Null cloud-region identifier!"); Objects.requireNonNull(tenantId, "Null tenant identifier!"); @@ -124,7 +163,11 @@ public class HeatBridgeImpl implements HeatBridgeApi { this.regionId = regionId; this.tenantId = tenantId; this.resourcesClient = resourcesClient; - this.transaction = resourcesClient.beginSingleTransaction(); + this.nodeType = nodeType; + if (resourcesClient != null) + this.transaction = resourcesClient.beginSingleTransaction(); + if (SpringContextHelper.getAppContext() != null) + this.env = SpringContextHelper.getAppContext().getEnvironment(); } public HeatBridgeImpl() { @@ -145,7 +188,7 @@ public class HeatBridgeImpl implements HeatBridgeApi { logger.trace("Keystone Version: {} ", keystoneVersion); this.osClient = new MsoCloudClientFactoryImpl(new OpenstackClientFactoryImpl()).getOpenstackClient( cloudIdentity.getIdentityUrl(), cloudIdentity.getMsoId(), cloudIdentity.getMsoPass(), regionId, - tenantId, keystoneVersion); + tenantId, keystoneVersion, cloudIdentity.getUserDomainName(), cloudIdentity.getProjectDomainName()); logger.trace("Successfully authenticated with keystone for tenant: {} and region: {}", tenantId, regionId); return osClient; } @@ -186,6 +229,21 @@ public class HeatBridgeImpl implements HeatBridgeApi { return serverIds.stream().map(serverId -> osClient.getServerById(serverId)).collect(Collectors.toList()); } + + protected Server getOpenstackServerById(String deviceId) { + return osClient.getServerById(deviceId); + } + + @Override + public List getAllOpenstackProviderNetworks(final List stackResources) { + Objects.requireNonNull(osClient, ERR_MSG_NULL_OS_CLIENT); + // Filter Openstack Compute resources + List providerNetworkIds = + extractStackResourceIdsByResourceType(stackResources, HeatBridgeConstants.OS_NEUTRON_PROVIDERNET); + return providerNetworkIds.stream().map(providerNetworkId -> osClient.getNetworkById(providerNetworkId)) + .collect(Collectors.toList()); + } + @Override public List extractOpenstackImagesFromServers(final List servers) { Objects.requireNonNull(osClient, ERR_MSG_NULL_OS_CLIENT); @@ -200,14 +258,36 @@ public class HeatBridgeImpl implements HeatBridgeApi { .filter(distinctByProperty(org.openstack4j.model.compute.Flavor::getId)).collect(Collectors.toList()); } + public void buildAddNetworksToAaiAction(final String genericVnfId, final String vfModuleId, + List networks) { + networks.forEach(network -> { + L3Network l3Network = aaiHelper.buildNetwork(network); + if (l3Network != null) { + l3Network.setSubnets(buildSunets(network)); + + RelationshipList relationshipList = new RelationshipList(); + List relationships = relationshipList.getRelationship(); + + relationships.add(aaiHelper.getRelationshipToVfModule(genericVnfId, vfModuleId)); + relationships.add(aaiHelper.getRelationshipToTenant(cloudOwner, cloudRegionId, tenantId)); + + l3Network.setRelationshipList(relationshipList); + transaction.createIfNotExists( + AAIUriFactory + .createResourceUri(AAIFluentTypeBuilder.network().l3Network(l3Network.getNetworkId())), + Optional.of(l3Network)); + } + }); + } + @Override public void buildAddImagesToAaiAction(final List images) throws HeatBridgeException { for (org.openstack4j.model.compute.Image image : images) { Image aaiImage = aaiHelper.buildImage(image); try { - AAIResourceUri uri = AAIUriFactory.createResourceUri(AAIObjectType.IMAGE, cloudOwner, cloudRegionId, - aaiImage.getImageId()); + AAIResourceUri uri = AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.cloudInfrastructure() + .cloudRegion(cloudOwner, cloudRegionId).image(aaiImage.getImageId())); if (!resourcesClient.exists(uri)) { transaction.create(uri, aaiImage); logger.debug("Queuing AAI command to add image: " + aaiImage.getImageId()); @@ -227,8 +307,8 @@ public class HeatBridgeImpl implements HeatBridgeApi { for (org.openstack4j.model.compute.Flavor flavor : flavors) { Flavor aaiFlavor = aaiHelper.buildFlavor(flavor); try { - AAIResourceUri uri = AAIUriFactory.createResourceUri(AAIObjectType.FLAVOR, cloudOwner, cloudRegionId, - aaiFlavor.getFlavorId()); + AAIResourceUri uri = AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.cloudInfrastructure() + .cloudRegion(cloudOwner, cloudRegionId).flavor(aaiFlavor.getFlavorId())); transaction.createIfNotExists(uri, Optional.of(aaiFlavor)); } catch (WebApplicationException e) { throw new HeatBridgeException( @@ -246,38 +326,79 @@ public class HeatBridgeImpl implements HeatBridgeApi { // Build vserver relationships to: image, flavor, pserver, vf-module vserver.setRelationshipList( aaiHelper.getVserverRelationshipList(cloudOwner, cloudRegionId, genericVnfId, vfModuleId, server)); - transaction.create(AAIUriFactory.createResourceUri(AAIObjectType.VSERVER, cloudOwner, cloudRegionId, - tenantId, vserver.getVserverId()), vserver); + transaction.createIfNotExists( + AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.cloudInfrastructure() + .cloudRegion(cloudOwner, cloudRegionId).tenant(tenantId).vserver(vserver.getVserverId())), + Optional.of(vserver)); }); } @Override public void buildAddVserverLInterfacesToAaiAction(final List stackResources, - final List oobMgtNetIds) { + final List oobMgtNetIds, String cloudOwner) throws HeatBridgeException { Objects.requireNonNull(osClient, ERR_MSG_NULL_OS_CLIENT); List portIds = extractStackResourceIdsByResourceType(stackResources, HeatBridgeConstants.OS_PORT_RESOURCE_TYPE); + + if (portIds == null) + return; for (String portId : portIds) { + boolean isL2Multicast = false; Port port = osClient.getPortById(portId); + Network network = osClient.getNetworkById(port.getNetworkId()); LInterface lIf = new LInterface(); lIf.setInterfaceId(port.getId()); lIf.setInterfaceName(port.getName()); lIf.setMacaddr(port.getMacAddress()); - lIf.setNetworkName((String) port.getProfile().get("physical_network")); + lIf.setNetworkName(network.getName()); lIf.setIsPortMirrored(false); lIf.setIsIpUnnumbered(false); lIf.setInMaint(false); + + if (port.getProfile() != null && port.getProfile().get("trusted") != null) { + String trusted = port.getProfile().get("trusted").toString(); + if (Boolean.parseBoolean(trusted)) { + isL2Multicast = true; + } + } + lIf.setL2Multicasting(isL2Multicast); + lIf.setInterfaceType(getInterfaceType(nodeType, port.getvNicType())); + lIf.setRelationshipList(new RelationshipList()); + if (oobMgtNetIds != null && oobMgtNetIds.contains(port.getNetworkId())) { lIf.setInterfaceRole(OOB_MGT_NETWORK_IDENTIFIER); } else { lIf.setInterfaceRole(port.getvNicType()); } - updateLInterfaceIps(port, lIf); - updateLInterfaceVlan(port, lIf); // Update l-interface to the vserver - transaction.create(AAIUriFactory.createResourceUri(AAIObjectType.L_INTERFACE, cloudOwner, cloudRegionId, - tenantId, port.getDeviceId(), lIf.getInterfaceName()), lIf); + transaction.createIfNotExists( + AAIUriFactory.createResourceUri( + AAIFluentTypeBuilder.cloudInfrastructure().cloudRegion(cloudOwner, cloudRegionId) + .tenant(tenantId).vserver(port.getDeviceId()).lInterface(lIf.getInterfaceName())), + Optional.of(lIf)); + + updateLInterfaceIps(port, lIf); + + if (cloudOwner.equals(env.getProperty("mso.cloudOwner.included", ""))) { + Server server = getOpenstackServerById(port.getDeviceId()); + updateLInterfaceVlan(port, lIf, server.getHypervisorHostname()); + } + + updateSriovPfToPserver(port, lIf); + } + } + + protected String getInterfaceType(NodeType nodeType, String nicType) { + logger.debug("nicType: " + nicType + "nodeType: " + nodeType); + if (DIRECT.equalsIgnoreCase(nicType)) { + return SRIOV; + } else { + if (nodeType == NodeType.GREENFIELD) { + return NodeType.GREENFIELD.getNetworkTechnologyName(); + } else { + return NodeType.BROWNFIELD.getNetworkTechnologyName(); + } } } @@ -294,8 +415,10 @@ public class HeatBridgeImpl implements HeatBridgeApi { for (String portId : portIds) { Port port = osClient.getPortById(portId); if (port.getvNicType().equalsIgnoreCase(HeatBridgeConstants.OS_SRIOV_PORT_TYPE)) { - createPServerPInterfaceIfNotExists(serverHostnames.get(port.getHostId()).getHostname(), - aaiHelper.buildPInterface(port)); + Pserver foundServer = serverHostnames.get(port.getHostId()); + if (foundServer != null) { + createPServerPInterfaceIfNotExists(foundServer.getHostname(), aaiHelper.buildPInterface(port)); + } } } } @@ -307,6 +430,7 @@ public class HeatBridgeImpl implements HeatBridgeApi { for (Server server : osServers) { Pserver pserver = aaiHelper.buildPserver(server); if (pserver != null) { + logger.debug("Adding Pserver: " + server.getHost()); pserverMap.put(server.getHost(), pserver); } } @@ -314,58 +438,142 @@ public class HeatBridgeImpl implements HeatBridgeApi { return pserverMap; } + private Subnets buildSunets(Network network) { + Subnets aaiSubnets = new Subnets(); + List subnetIds = network.getSubnets(); + + subnetIds.forEach(subnetId -> { + Subnet subnet = osClient.getSubnetById(subnetId); + org.onap.aai.domain.yang.Subnet aaiSubnet = aaiHelper.buildSubnet(subnet); + if (aaiSubnet != null) { + aaiSubnets.getSubnet().add(aaiSubnet); + } + }); + return aaiSubnets; + } + private void createPServerIfNotExists(Map serverHostnames) { for (Pserver pserver : serverHostnames.values()) { - AAIResourceUri uri = AAIUriFactory.createResourceUri(AAIObjectType.PSERVER, pserver.getHostname()); + AAIResourceUri uri = AAIUriFactory + .createResourceUri(AAIFluentTypeBuilder.cloudInfrastructure().pserver(pserver.getHostname())); resourcesClient.createIfNotExists(uri, Optional.of(pserver)); } } private void createPServerPInterfaceIfNotExists(String pserverHostname, PInterface pInterface) { - AAIResourceUri uri = AAIUriFactory.createResourceUri(AAIObjectType.P_INTERFACE, pserverHostname, - pInterface.getInterfaceName()); + AAIResourceUri uri = AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.cloudInfrastructure() + .pserver(pserverHostname).pInterface(pInterface.getInterfaceName())); resourcesClient.createIfNotExists(uri, Optional.of(pInterface)); } - private void updateLInterfaceVlan(final Port port, final LInterface lIf) { + protected void updateLInterfaceVlan(final Port port, final LInterface lIf, final String hostName) + throws HeatBridgeException { + // add back all vlan logic Vlan vlan = new Vlan(); Network network = osClient.getNetworkById(port.getNetworkId()); - if (network.getNetworkType().equals(NetworkType.VLAN)) { - vlan.setVlanInterface(network.getName() + network.getProviderSegID()); - + if (network.getNetworkType() != null && network.getNetworkType().equals(NetworkType.VLAN)) { + vlan.setVlanInterface(port.getName() + network.getProviderSegID()); vlan.setVlanIdOuter(Long.parseLong(network.getProviderSegID())); vlan.setVlanIdInner(0L); vlan.setInMaint(false); vlan.setIsIpUnnumbered(false); vlan.setIsPrivate(false); - Vlans vlans = new Vlans(); - List vlanList = vlans.getVlan(); - vlanList.add(vlan); - lIf.setVlans(vlans); + transaction + .createIfNotExists( + AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.cloudInfrastructure() + .cloudRegion(cloudOwner, cloudRegionId).tenant(tenantId).vserver(port.getDeviceId()) + .lInterface(lIf.getInterfaceName()).vlan(vlan.getVlanInterface())), + Optional.of(vlan)); } - // Build sriov-vf to the l-interface - if (port.getvNicType().equalsIgnoreCase(HeatBridgeConstants.OS_SRIOV_PORT_TYPE)) { - SriovVfs sriovVfs = new SriovVfs(); - // JAXB does not generate setters for list, however getter ensures its creation. - // Thus, all list manipulations must be made on live list. - List sriovVfList = sriovVfs.getSriovVf(); + + if (!lIf.getInterfaceType().equals(SRIOV)) { + if (nodeType == NodeType.GREENFIELD) { + validatePhysicalNetwork(port, network); + processOVS(lIf, hostName, NodeType.GREENFIELD.getInterfaceName()); + } else { + processOVS(lIf, hostName, NodeType.BROWNFIELD.getInterfaceName()); + } + } + + List privateVlans = (ArrayList) port.getProfile().get(PRIVATE_VLANS); + List publicVlans = (ArrayList) port.getProfile().get(PUBLIC_VLANS); + List vlans = null; + if (publicVlans != null && !publicVlans.isEmpty()) { + vlans = publicVlans.stream().filter(publicVlan -> !Strings.isNullOrEmpty(publicVlan)) + .collect(Collectors.toList()); + } else { + vlans = new ArrayList<>(); + } + + if (privateVlans != null && !privateVlans.isEmpty()) { + List temp = privateVlans.stream().filter(privateVlan -> !Strings.isNullOrEmpty(privateVlan)) + .collect(Collectors.toList()); + vlans.addAll(temp); + } + vlans.stream().forEach(vlanLocal -> logger.debug("Vlan Id: {}", vlanLocal)); + + processVlanTag(lIf, vlans); + + if (port.getvNicType() != null && port.getvNicType().equalsIgnoreCase(HeatBridgeConstants.OS_SRIOV_PORT_TYPE)) { SriovVf sriovVf = new SriovVf(); sriovVf.setPciId(port.getProfile().get(HeatBridgeConstants.OS_PCI_SLOT_KEY).toString()); sriovVf.setNeutronNetworkId(port.getNetworkId()); - if (port.getVifDetails() != null) { - sriovVf.setVfVlanFilter((String) port.getVifDetails().get(HeatBridgeConstants.OS_VLAN_NETWORK_KEY)); - } + sriovVf.setVfVlanFilter("0"); sriovVf.setVfVlanAntiSpoofCheck(false); sriovVf.setVfMacAntiSpoofCheck(false); - sriovVfList.add(sriovVf); - lIf.setSriovVfs(sriovVfs); + transaction + .createIfNotExists( + AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.cloudInfrastructure() + .cloudRegion(cloudOwner, cloudRegionId).tenant(tenantId).vserver(port.getDeviceId()) + .lInterface(lIf.getInterfaceName()).sriovVf(sriovVf.getPciId())), + Optional.of(sriovVf)); + } + } + + protected String createVlanTagUri(String vlanIdOuter) throws HeatBridgeException { + int vlanOuterInt = Integer.parseInt(vlanIdOuter); + DSLQueryBuilder builder = TraversalBuilder + .fragment(new DSLStartNode(Types.CLOUD_REGION, __.key("cloud-owner", cloudOwner), + __.key("cloud-region-id", cloudRegionId))) + .to(__.node(Types.VLAN_RANGE)) + .to(__.node(Types.VLAN_TAG, __.key("vlan-id-outer", vlanOuterInt)).output()); + String results = getAAIDSLClient().query(Format.PATHED, new DSLQuery(builder.build())); + Optional vlanTagURI = findLinkedURI(results); + if (vlanTagURI.isPresent()) + return vlanTagURI.get(); + else + throw new HeatBridgeException("Cannot find VlanTag Related Link " + vlanIdOuter); + } + - // For the given port create sriov-pf for host pserver/p-interface if absent - updateSriovPfToPserver(port, lIf); + protected void processVlanTag(LInterface lInterface, List vlanTags) throws HeatBridgeException { + for (String vlanTag : vlanTags) { + Relationship vlanTagRelationship = new Relationship(); + vlanTagRelationship.setRelatedLink(createVlanTagUri(vlanTag)); + lInterface.getRelationshipList().getRelationship().add(vlanTagRelationship); + } + } + + protected void validatePhysicalNetwork(Port neutronPort, Network network) throws HeatBridgeException { + String physicalNetworkType = network.getProviderPhyNet(); + if (!OVSNET.equalsIgnoreCase(physicalNetworkType)) { + String exceptionMessage = String.format( + "The OVS-DPDK port is expected to have a physical network of type ovsnet but was found to have %s instead.", + physicalNetworkType); + throw new HeatBridgeException(exceptionMessage); } } + protected void processOVS(LInterface lInterface, String hostName, String interfaceName) { + Relationship lagRelationship = new Relationship(); + lagRelationship.setRelatedLink(AAIUriFactory + .createResourceUri( + AAIFluentTypeBuilder.cloudInfrastructure().pserver(hostName).lagInterface(interfaceName)) + .build().toString()); + lInterface.getRelationshipList().getRelationship().add(lagRelationship); + } + /** * Needs to be corrected according to the specification that is in draft If pserver/p-interface does not have a * SRIOV-PF object matching the PCI-ID of the Openstack port object, then create it in AAI. Openstack SRIOV Port @@ -376,63 +584,102 @@ public class HeatBridgeImpl implements HeatBridgeApi { * @param lIf AAI l-interface object */ private void updateSriovPfToPserver(final Port port, final LInterface lIf) { - if (port.getProfile() == null || Strings - .isNullOrEmpty(port.getProfile().get(HeatBridgeConstants.OS_PHYSICAL_NETWORK_KEY).toString())) { - logger.debug("The SRIOV port:" + port.getName() + " is missing physical-network-id, cannot update " - + "sriov-pf object for host pserver: " + port.getHostId()); - return; - } - Optional matchingPifName = HeatBridgeUtils.getMatchingPserverPifName( - port.getProfile().get(HeatBridgeConstants.OS_PHYSICAL_NETWORK_KEY).toString()); - if (matchingPifName.isPresent()) { - // Update l-interface description - String pserverHostName = port.getHostId(); - lIf.setInterfaceDescription("Attached to SR-IOV port: " + pserverHostName + "::" + matchingPifName.get()); - try { - Optional matchingPIf = resourcesClient.get(PInterface.class, - AAIUriFactory - .createResourceUri(AAIObjectType.P_INTERFACE, pserverHostName, matchingPifName.get()) - .depth(Depth.ONE)); - if (matchingPIf.isPresent()) { - SriovPfs pIfSriovPfs = matchingPIf.get().getSriovPfs(); - if (pIfSriovPfs == null) { - pIfSriovPfs = new SriovPfs(); - } - // Extract PCI-ID from OS port object - String pfPciId = port.getProfile().get(HeatBridgeConstants.OS_PCI_SLOT_KEY).toString(); - - List existingSriovPfs = pIfSriovPfs.getSriovPf(); - if (CollectionUtils.isEmpty(existingSriovPfs) || existingSriovPfs.stream() - .noneMatch(existingSriovPf -> existingSriovPf.getPfPciId().equals(pfPciId))) { - // Add sriov-pf object with PCI-ID to AAI - SriovPf sriovPf = new SriovPf(); - sriovPf.setPfPciId(pfPciId); - logger.debug("Queuing AAI command to update sriov-pf object to pserver: " + pserverHostName - + "/" + matchingPifName.get()); - transaction.create(AAIUriFactory.createResourceUri(AAIObjectType.SRIOV_PF, pserverHostName, - matchingPifName.get(), sriovPf.getPfPciId()), sriovPf); + if (port.getvNicType().equalsIgnoreCase(HeatBridgeConstants.OS_SRIOV_PORT_TYPE)) { + if (port.getProfile() == null || Strings + .isNullOrEmpty(port.getProfile().get(HeatBridgeConstants.OS_PHYSICAL_NETWORK_KEY).toString())) { + logger.debug("The SRIOV port:" + port.getName() + " is missing physical-network-id, cannot update " + + "sriov-pf object for host pserver: " + port.getHostId()); + return; + } + Optional matchingPifName = HeatBridgeUtils.getMatchingPserverPifName( + port.getProfile().get(HeatBridgeConstants.OS_PHYSICAL_NETWORK_KEY).toString()); + if (matchingPifName.isPresent()) { + // Update l-interface description + String pserverHostName = port.getHostId(); + lIf.setInterfaceDescription( + "Attached to SR-IOV port: " + pserverHostName + "::" + matchingPifName.get()); + try { + Optional matchingPIf = resourcesClient.get(PInterface.class, + AAIUriFactory + .createResourceUri(AAIFluentTypeBuilder.cloudInfrastructure() + .pserver(pserverHostName).pInterface(matchingPifName.get())) + .depth(Depth.ONE)); + if (matchingPIf.isPresent()) { + SriovPfs pIfSriovPfs = matchingPIf.get().getSriovPfs(); + if (pIfSriovPfs == null) { + pIfSriovPfs = new SriovPfs(); + } + // Extract PCI-ID from OS port object + String pfPciId = port.getProfile().get(HeatBridgeConstants.OS_PCI_SLOT_KEY).toString(); + + List existingSriovPfs = pIfSriovPfs.getSriovPf(); + if (CollectionUtils.isEmpty(existingSriovPfs) || existingSriovPfs.stream() + .noneMatch(existingSriovPf -> existingSriovPf.getPfPciId().equals(pfPciId))) { + // Add sriov-pf object with PCI-ID to AAI + SriovPf sriovPf = new SriovPf(); + sriovPf.setPfPciId(pfPciId); + logger.debug("Queuing AAI command to update sriov-pf object to pserver: " + pserverHostName + + "/" + matchingPifName.get()); + + AAIResourceUri sriovPfUri = AAIUriFactory.createResourceUri( + AAIFluentTypeBuilder.cloudInfrastructure().pserver(pserverHostName) + .pInterface(matchingPifName.get()).sriovPf(sriovPf.getPfPciId())); + + + if (!resourcesClient.exists(sriovPfUri)) { + transaction.create(sriovPfUri, sriovPf); + + AAIResourceUri sriovVfUri = AAIUriFactory.createResourceUri(AAIFluentTypeBuilder + .cloudInfrastructure().cloudRegion(cloudOwner, cloudRegionId).tenant(tenantId) + .vserver(port.getDeviceId()).lInterface(lIf.getInterfaceName()).sriovVf( + port.getProfile().get(HeatBridgeConstants.OS_PCI_SLOT_KEY).toString())); + transaction.connect(sriovPfUri, sriovVfUri); + } + } } + } catch (WebApplicationException e) { + // Silently log that we failed to update the Pserver p-interface with PCI-ID + logger.error(LoggingAnchor.NINE, MessageEnum.GENERAL_EXCEPTION, pserverHostName, + matchingPifName.get(), cloudOwner, tenantId, "OpenStack", "Heatbridge", + ErrorCode.DataError.getValue(), "Exception - Failed to add sriov-pf object to pserver", e); } - } catch (WebApplicationException e) { - // Silently log that we failed to update the Pserver p-interface with PCI-ID - logger.error(LoggingAnchor.NINE, MessageEnum.GENERAL_EXCEPTION, pserverHostName, matchingPifName.get(), - cloudOwner, tenantId, "OpenStack", "Heatbridge", ErrorCode.DataError.getValue(), - "Exception - Failed to add sriov-pf object to pserver", e); } } } - private void updateLInterfaceIps(final Port port, final LInterface lIf) { - List lInterfaceIps = lIf.getL3InterfaceIpv4AddressList(); + protected void updateLInterfaceIps(final Port port, final LInterface lIf) { for (IP ip : port.getFixedIps()) { String ipAddress = ip.getIpAddress(); if (InetAddressValidator.getInstance().isValidInet4Address(ipAddress)) { + Subnet subnet = osClient.getSubnetById(ip.getSubnetId()); + IPAddressString cidr = new IPAddressString(subnet.getCidr()); L3InterfaceIpv4AddressList lInterfaceIp = new L3InterfaceIpv4AddressList(); + lInterfaceIp.setIsFloating(false); lInterfaceIp.setL3InterfaceIpv4Address(ipAddress); lInterfaceIp.setNeutronNetworkId(port.getNetworkId()); lInterfaceIp.setNeutronSubnetId(ip.getSubnetId()); - lInterfaceIp.setL3InterfaceIpv4PrefixLength(32L); - lInterfaceIps.add(lInterfaceIp); + lInterfaceIp.setL3InterfaceIpv4PrefixLength(Long.parseLong(cidr.getNetworkPrefixLength().toString())); + + transaction.createIfNotExists( + AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.cloudInfrastructure() + .cloudRegion(cloudOwner, cloudRegionId).tenant(tenantId).vserver(port.getDeviceId()) + .lInterface(lIf.getInterfaceName()).l3InterfaceIpv4AddressList(ipAddress)), + Optional.of(lInterfaceIp)); + } else if (InetAddressValidator.getInstance().isValidInet6Address(ipAddress)) { + Subnet subnet = osClient.getSubnetById(ip.getSubnetId()); + IPAddressString cidr = new IPAddressString(subnet.getCidr()); + L3InterfaceIpv6AddressList ipv6 = new L3InterfaceIpv6AddressList(); + ipv6.setIsFloating(false); + ipv6.setL3InterfaceIpv6Address(ipAddress); + ipv6.setNeutronNetworkId(port.getNetworkId()); + ipv6.setNeutronSubnetId(ip.getSubnetId()); + ipv6.setL3InterfaceIpv6PrefixLength(Long.parseLong(cidr.getNetworkPrefixLength().toString())); + + transaction.createIfNotExists( + AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.cloudInfrastructure() + .cloudRegion(cloudOwner, cloudRegionId).tenant(tenantId).vserver(port.getDeviceId()) + .lInterface(lIf.getInterfaceName()).l3InterfaceIpv6AddressList(ipAddress)), + Optional.of(ipv6)); } } } @@ -454,27 +701,47 @@ public class HeatBridgeImpl implements HeatBridgeApi { Objects.requireNonNull(vnfId, "Null vnf-id!"); Objects.requireNonNull(vfModuleId, "Null vf-module-id!"); try { - Optional vfModule = resourcesClient.get(VfModule.class, - AAIUriFactory.createResourceUri(AAIObjectType.VF_MODULE, vnfId, vfModuleId).depth(Depth.ONE)); - logger.debug("vfModule is present: {}", vfModule.isPresent()); - if (vfModule.isPresent()) { - - AAIResultWrapper resultWrapper = new AAIResultWrapper(vfModule.get()); - Optional relationships = resultWrapper.getRelationships(); - logger.debug("relationships is present: {}", relationships.isPresent()); - if (relationships.isPresent()) { - List vserverUris = relationships.get().getRelatedUris(AAIObjectType.VSERVER); - logger.debug("vserverList isEmpty: {}", vserverUris.isEmpty()); - createTransactionToDeleteSriovPfFromPserver(vserverUris); - - if (!vserverUris.isEmpty()) { - for (AAIResourceUri vserverUri : vserverUris) { - logger.debug("Deleting Vservers: {}", vserverUri.toString()); + Optional vfModule = resourcesClient.get(AAIUriFactory + .createResourceUri(AAIFluentTypeBuilder.network().genericVnf(vnfId).vfModule(vfModuleId)) + .depth(Depth.ONE), NotFoundException.class).asBean(VfModule.class); + + AAIResultWrapper resultWrapper = new AAIResultWrapper(vfModule.get()); + Optional relationships = resultWrapper.getRelationships(); + logger.debug("VfModule contains relationships in AAI: {}", relationships.isPresent()); + if (relationships.isPresent()) { + + List l3NetworkUris = relationships.get().getRelatedUris(Types.L3_NETWORK); + logger.debug("L3Network contains {} relationships in AAI", l3NetworkUris.size()); + + if (!l3NetworkUris.isEmpty()) { + for (AAIResourceUri l3NetworkUri : l3NetworkUris) { + if (env.getProperty("heatBridgeDryrun", Boolean.class, true)) { + logger.debug("Would delete L3Network: {}", l3NetworkUri.build().toString()); + } else { + resourcesClient.delete(l3NetworkUri); + } + } + } + + List vserverUris = relationships.get().getRelatedUris(Types.VSERVER); + logger.debug("VServer contains {} relationships in AAI", vserverUris.size()); + createTransactionToDeleteSriovPfFromPserver(vserverUris); + + if (!vserverUris.isEmpty()) { + for (AAIResourceUri vserverUri : vserverUris) { + if (env.getProperty("heatBridgeDryrun", Boolean.class, false)) { + logger.debug("Would delete Vserver: {}", vserverUri.build().toString()); + } else { resourcesClient.delete(vserverUri); } } } } + + } catch (NotFoundException e) { + String msg = "Failed to commit delete heatbridge data transaction"; + logger.debug(msg + " with error: " + e); + throw new HeatBridgeException(msg, e); } catch (Exception e) { String msg = "Failed to commit delete heatbridge data transaction"; logger.debug(msg + " with error: " + e); @@ -488,7 +755,8 @@ public class HeatBridgeImpl implements HeatBridgeApi { String pserverName = entry.getKey(); List pciIds = entry.getValue(); Optional pserver = resourcesClient.get(Pserver.class, - AAIUriFactory.createResourceUri(AAIObjectType.PSERVER, pserverName).depth(Depth.TWO)); + AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.cloudInfrastructure().pserver(pserverName)) + .depth(Depth.TWO)); if (pserver.isPresent()) { // For each pserver/p-interface match sriov-vfs by pic-id and delete them. pserver.get().getPInterfaces().getPInterface().stream().filter( @@ -497,8 +765,16 @@ public class HeatBridgeImpl implements HeatBridgeApi { if (pciIds.contains(sriovPf.getPfPciId())) { logger.debug("creating transaction to delete SR-IOV PF: " + pIf.getInterfaceName() + " from PServer: " + pserverName); - resourcesClient.delete(AAIUriFactory.createResourceUri(AAIObjectType.SRIOV_PF, - pserverName, pIf.getInterfaceName(), sriovPf.getPfPciId())); + if (env.getProperty("heatBridgeDryrun", Boolean.class, false)) { + logger.debug("Would delete Sriov Pf: {}", + AAIUriFactory.createResourceUri(AAIFluentTypeBuilder.cloudInfrastructure() + .pserver(pserverName).pInterface(pIf.getInterfaceName()) + .sriovPf(sriovPf.getPfPciId())).build()); + } else { + resourcesClient.delete(AAIUriFactory.createResourceUri( + AAIFluentTypeBuilder.cloudInfrastructure().pserver(pserverName) + .pInterface(pIf.getInterfaceName()).sriovPf(sriovPf.getPfPciId()))); + } } })); } @@ -511,13 +787,13 @@ public class HeatBridgeImpl implements HeatBridgeApi { AAIResultWrapper vserverWrapper = resourcesClient.get(vserverUri.depth(Depth.TWO)); Optional vserverRelationships = vserverWrapper.getRelationships(); if (vserverRelationships.isPresent() - && CollectionUtils.isNotEmpty(vserverRelationships.get().getRelatedLinks(AAIObjectType.PSERVER))) { + && CollectionUtils.isNotEmpty(vserverRelationships.get().getRelatedLinks(Types.PSERVER))) { Vserver vserver = vserverWrapper.asBean(Vserver.class).get(); List pciIds = HeatBridgeUtils.extractPciIdsFromVServer(vserver); if (CollectionUtils.isNotEmpty(pciIds)) { - List matchingPservers = vserverRelationships.get().getRelatedLinks(AAIObjectType.PSERVER); + List matchingPservers = vserverRelationships.get().getRelatedUris(Types.PSERVER); if (matchingPservers != null && matchingPservers.size() == 1) { - pserverToPciIdMap.put(matchingPservers.get(0), pciIds); + pserverToPciIdMap.put(matchingPservers.get(0).getURIKeys().get("hostname"), pciIds); } } } @@ -529,4 +805,28 @@ public class HeatBridgeImpl implements HeatBridgeApi { Map map = new ConcurrentHashMap<>(); return t -> map.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null; } + + protected Optional findLinkedURI(String jsonResultsString) { + Results> results; + try { + results = mapper.readValue(jsonResultsString, new TypeReference>>() {}); + if (results.getResult().size() == 1) { + return Optional.of(results.getResult().get(0).get(RESOURCE_LINK)); + } else if (results.getResult().isEmpty()) { + return Optional.empty(); + } else { + throw new IllegalStateException("more than one result returned"); + } + } catch (IOException e) { + logger.error("Error retrieving URI from Results JSON", e); + return Optional.empty(); + } + } + + protected AAIDSLQueryClient getAAIDSLClient() { + if (aaiDSLClient == null) { + aaiDSLClient = new AAIDSLQueryClient(); + } + return aaiDSLClient; + } }