[SO] heatbridge implemention to populate AAI with openstack provider network/subnet 41/110741/6
authorMunir Ahmad <munir.ahmad@bell.ca>
Thu, 30 Jul 2020 14:24:50 +0000 (10:24 -0400)
committerMunir Ahmad <munir.ahmad@bell.ca>
Tue, 4 Aug 2020 15:19:24 +0000 (11:19 -0400)
Issue-ID: SO-3109

Signed-off-by: Munir Ahmad <munir.ahmad@bell.ca>
Change-Id: Ibb8f5b994072b797783dba7ce412baecb9b64174

adapters/mso-openstack-adapters/src/main/java/org/onap/so/adapters/tasks/inventory/CreateAAIInventory.java
adapters/mso-openstack-adapters/src/main/java/org/onap/so/heatbridge/HeatBridgeApi.java
adapters/mso-openstack-adapters/src/main/java/org/onap/so/heatbridge/HeatBridgeImpl.java
adapters/mso-openstack-adapters/src/main/java/org/onap/so/heatbridge/constants/HeatBridgeConstants.java
adapters/mso-openstack-adapters/src/main/java/org/onap/so/heatbridge/helpers/AaiHelper.java
adapters/mso-openstack-adapters/src/test/java/org/onap/so/heatbridge/HeatBridgeImplTest.java

index df4229c..12751f8 100644 (file)
@@ -35,6 +35,7 @@ import org.openstack4j.model.compute.Flavor;
 import org.openstack4j.model.compute.Image;
 import org.openstack4j.model.compute.Server;
 import org.openstack4j.model.heat.Resource;
+import org.openstack4j.model.network.Network;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -72,6 +73,10 @@ public class CreateAAIInventory {
             List<Resource> stackResources =
                     heatBridgeClient.queryNestedHeatStackResources(cloudInformation.getTemplateInstanceId());
 
+            List<Network> osNetworks = heatBridgeClient.getAllOpenstackProviderNetworks(stackResources);
+            heatBridgeClient.buildAddNetworksToAaiAction(cloudInformation.getVnfId(), cloudInformation.getVfModuleId(),
+                    osNetworks);
+
             List<Server> osServers = heatBridgeClient.getAllOpenstackServers(stackResources);
 
             heatBridgeClient.createPserversAndPinterfacesIfNotPresentInAai(stackResources);
index 9c09886..a4e6ccc 100644 (file)
@@ -38,6 +38,7 @@ import org.openstack4j.model.compute.Flavor;
 import org.openstack4j.model.compute.Image;
 import org.openstack4j.model.compute.Server;
 import org.openstack4j.model.heat.Resource;
+import org.openstack4j.model.network.Network;
 
 /**
  * Defines the contract to extract Heat Stack Resources from Openstack and inventory it to AAI. This API is used only to
@@ -87,6 +88,14 @@ public interface HeatBridgeApi {
      */
     List<Server> getAllOpenstackServers(List<Resource> stackResources);
 
+    /**
+     * Query the Openstack provider network objects from the list of stack resources
+     *
+     * @param stackResources A list of stack based resources
+     * @return A list of Openstack Network objects
+     */
+    List<Network> getAllOpenstackProviderNetworks(final List<Resource> stackResources);
+
     /**
      * Extract Openstack Image objects from a a list of Server objects
      *
@@ -103,6 +112,15 @@ public interface HeatBridgeApi {
      */
     List<Flavor> extractOpenstackFlavorsFromServers(List<Server> servers);
 
+    /**
+     * Query and build AAI actions for Openstack Compute resources to AAI's l3-network objects with its subnets
+     *
+     * @param genericVnfId AAI generic-vnf-id
+     * @param vfModuleId AAI vf-module-id
+     * @param networks Openstack Network list
+     */
+    void buildAddNetworksToAaiAction(final String genericVnfId, final String vfModuleId, List<Network> networks);
+
     /**
      * Query and build AAI actions for Openstack Image resources to AAI's image objects
      *
index e537b24..9295800 100644 (file)
@@ -49,11 +49,15 @@ 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.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;
@@ -197,6 +201,16 @@ public class HeatBridgeImpl implements HeatBridgeApi {
         return serverIds.stream().map(serverId -> osClient.getServerById(serverId)).collect(Collectors.toList());
     }
 
+    @Override
+    public List<Network> getAllOpenstackProviderNetworks(final List<Resource> stackResources) {
+        Objects.requireNonNull(osClient, ERR_MSG_NULL_OS_CLIENT);
+        // Filter Openstack Compute resources
+        List<String> providerNetworkIds =
+                extractStackResourceIdsByResourceType(stackResources, HeatBridgeConstants.OS_NEUTRON_PROVIDERNET);
+        return providerNetworkIds.stream().map(providerNetworkId -> osClient.getNetworkById(providerNetworkId))
+                .collect(Collectors.toList());
+    }
+
     @Override
     public List<org.openstack4j.model.compute.Image> extractOpenstackImagesFromServers(final List<Server> servers) {
         Objects.requireNonNull(osClient, ERR_MSG_NULL_OS_CLIENT);
@@ -211,6 +225,27 @@ 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<Network> networks) {
+        networks.forEach(network -> {
+            L3Network l3Network = aaiHelper.buildNetwork(network);
+            if (l3Network != null) {
+                l3Network.setSubnets(buildSunets(network));
+
+                RelationshipList relationshipList = new RelationshipList();
+                List<Relationship> relationships = relationshipList.getRelationship();
+
+                relationships.add(aaiHelper.getRelationshipToVfModule(genericVnfId, vfModuleId));
+                relationships.add(aaiHelper.getRelationshipToTenant(cloudOwner, cloudRegionId, tenantId));
+
+                l3Network.setRelationshipList(relationshipList);
+                transaction.createIfNotExists(
+                        AAIUriFactory.createResourceUri(AAIObjectType.L3_NETWORK, l3Network.getNetworkId()),
+                        Optional.of(l3Network));
+            }
+        });
+    }
+
     @Override
     public void buildAddImagesToAaiAction(final List<org.openstack4j.model.compute.Image> images)
             throws HeatBridgeException {
@@ -338,6 +373,20 @@ public class HeatBridgeImpl implements HeatBridgeApi {
         return pserverMap;
     }
 
+    private Subnets buildSunets(Network network) {
+        Subnets aaiSubnets = new Subnets();
+        List<String> 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<String, Pserver> serverHostnames) {
         for (Pserver pserver : serverHostnames.values()) {
             AAIResourceUri uri = AAIUriFactory.createResourceUri(AAIObjectType.PSERVER, pserver.getHostname());
index fdf7ce3..71c6a96 100644 (file)
@@ -40,6 +40,7 @@ public class HeatBridgeConstants {
     public static final Integer OS_DEFAULT_HEAT_NESTING = 5;
     public static final String OS_SERVER_RESOURCE_TYPE = "OS::Nova::Server";
     public static final String OS_PORT_RESOURCE_TYPE = "OS::Neutron::Port";
+    public static final String OS_NEUTRON_PROVIDERNET = "OS::Neutron::ProviderNet";
     public static final String OS_SRIOV_PORT_TYPE = "direct";
     public static final String OS_PCI_SLOT_KEY = "pci_slot";
     public static final String OS_PHYSICAL_NETWORK_KEY = "physical_network";
@@ -64,6 +65,8 @@ public class HeatBridgeConstants {
     public static final String AAI_VF_MODULE_ID = "vf-module.vf-module-id";
     public static final String AAI_IMAGE = "image";
     public static final String AAI_IMAGE_ID = "image.image-id";
+    public static final String AAI_TENANT = "tenant";
+    public static final String AAI_TENANT_ID = "tenant.tenant-id";
     public static final String AAI_CLOUD_OWNER = "cloud-region.cloud-owner";
     public static final String AAI_CLOUD_REGION_ID = "cloud-region.cloud-region-id";
     public static final String AAI_FLAVOR = "flavor";
index c4d9cbe..7d4e92d 100644 (file)
@@ -42,6 +42,7 @@ import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.onap.aai.domain.yang.Flavor;
 import org.onap.aai.domain.yang.Image;
+import org.onap.aai.domain.yang.L3Network;
 import org.onap.aai.domain.yang.PInterface;
 import org.onap.aai.domain.yang.Pserver;
 import org.onap.aai.domain.yang.Relationship;
@@ -54,7 +55,9 @@ import org.onap.aaiclient.client.aai.entities.uri.AAIResourceUri;
 import org.onap.aaiclient.client.aai.entities.uri.AAIUriFactory;
 import org.onap.so.heatbridge.constants.HeatBridgeConstants;
 import org.openstack4j.model.compute.Server;
+import org.openstack4j.model.network.Network;
 import org.openstack4j.model.network.Port;
+import org.openstack4j.model.network.Subnet;
 import com.google.common.base.Preconditions;
 
 /**
@@ -131,6 +134,49 @@ public class AaiHelper {
         return relationshipList;
     }
 
+    public Relationship getRelationshipToVfModule(String vnfId, String vfModuleId) {
+        return buildRelationship(AAIUriFactory.createResourceUri(AAIObjectType.VF_MODULE, vnfId, vfModuleId));
+    }
+
+    public Relationship getRelationshipToTenant(String cloudOwner, String cloudRegionId, String tenantId) {
+        return buildRelationship(
+                AAIUriFactory.createResourceUri(AAIObjectType.TENANT, cloudOwner, cloudRegionId, tenantId));
+    }
+
+    public org.onap.aai.domain.yang.Subnet buildSubnet(Subnet subnet) {
+        org.onap.aai.domain.yang.Subnet aaiSubnet = new org.onap.aai.domain.yang.Subnet();
+        aaiSubnet.setSubnetId(subnet.getId());
+        aaiSubnet.setDhcpEnabled(subnet.isDHCPEnabled());
+
+        aaiSubnet.setSubnetName(subnet.getName());
+        aaiSubnet.setGatewayAddress(subnet.getGateway());
+        aaiSubnet.setCidrMask(subnet.getCidr());
+        aaiSubnet.setIpVersion(subnet.getIpVersion().name());
+        return aaiSubnet;
+    }
+
+    public L3Network buildNetwork(Network network) {
+        if (network.getId() == null) {
+            return null;
+        }
+        L3Network l3Network = new L3Network();
+        l3Network.setNetworkId(network.getId());
+        l3Network.setIsBoundToVpn(true);
+        l3Network.setIsProviderNetwork(true);
+
+        // optional fields
+        l3Network.setIsSharedNetwork(network.isShared());
+        l3Network.setIsExternalNetwork(network.isRouterExternal());
+        l3Network.setOperationalStatus(String.valueOf(network.isAdminStateUp()));
+        if (network.getName() != null) {
+            l3Network.setNetworkName(network.getName());
+        }
+        if (network.getProviderPhyNet() != null) {
+            l3Network.setPhysicalNetworkName(network.getProviderPhyNet());
+        }
+        return l3Network;
+    }
+
     /**
      * Transform Openstack Server object to AAI Vserver object
      *
index 643dd4c..8c21e3f 100644 (file)
@@ -85,9 +85,11 @@ import org.openstack4j.model.compute.Server;
 import org.openstack4j.model.compute.Server.Status;
 import org.openstack4j.model.heat.Resource;
 import org.openstack4j.model.network.IP;
+import org.openstack4j.model.network.IPVersionType;
 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.openstack4j.openstack.heat.domain.HeatResource;
 import org.openstack4j.openstack.heat.domain.HeatResource.Resources;
 import org.springframework.core.env.Environment;
@@ -449,6 +451,70 @@ public class HeatBridgeImplTest {
         verify(osClient, times(10)).getNetworkById(anyString());
     }
 
+    @Test
+    public void testUpdateNetworksToAai() throws HeatBridgeException {
+
+        Subnet subnet1 = mock(Subnet.class);
+        when(subnet1.getId()).thenReturn("test-subnet1-id");
+        when(subnet1.getName()).thenReturn("test-subnet1-name");
+        when(subnet1.isDHCPEnabled()).thenReturn(true);
+        when(subnet1.getGateway()).thenReturn("test-subnet1-gateway");
+        when(subnet1.getCidr()).thenReturn("test-subnet1-gateway");
+        when(subnet1.getIpVersion()).thenReturn(IPVersionType.V4);
+
+        Subnet subnet2 = mock(Subnet.class);
+        when(subnet2.getId()).thenReturn("test-subnet2-id");
+        when(subnet2.getName()).thenReturn("test-subnet2-name");
+        when(subnet2.isDHCPEnabled()).thenReturn(true);
+        when(subnet2.getGateway()).thenReturn("test-subnet1-gateway");
+        when(subnet2.getCidr()).thenReturn("test-subnet1-gateway");
+        when(subnet2.getIpVersion()).thenReturn(IPVersionType.V6);
+
+        when(osClient.getSubnetById(subnet1.getId())).thenReturn(subnet1);
+        when(osClient.getSubnetById(subnet2.getId())).thenReturn(subnet2);
+
+        List<String> subnetIds = Arrays.asList(subnet1.getId(), subnet2.getId());
+
+        // Arrange
+        Network network1 = mock(Network.class);
+        when(network1.getId()).thenReturn("test-network1-id");
+        when(network1.isShared()).thenReturn(true);
+        when(network1.isRouterExternal()).thenReturn(true);
+        when(network1.isAdminStateUp()).thenReturn(true);
+        when(network1.getProviderPhyNet()).thenReturn("sriov-network1");
+        when(network1.getName()).thenReturn("network1");
+        when(network1.getSubnets()).thenReturn(subnetIds);
+
+        Network network2 = mock(Network.class);
+        when(network2.getId()).thenReturn("test-network2-id");
+        when(network2.isShared()).thenReturn(true);
+        when(network2.isRouterExternal()).thenReturn(true);
+        when(network2.isAdminStateUp()).thenReturn(true);
+        when(network2.getProviderPhyNet()).thenReturn("sriov-network2");
+        when(network2.getName()).thenReturn("network2");
+        when(network2.getSubnets()).thenReturn(subnetIds);
+
+        String vnfId = "some-uuiid-of-the-vnf";
+        String vfModuleId = "some-uuiid-of-the-vf-module";
+
+        Subnet subnet = mock(Subnet.class);
+
+        List<Network> networks = Arrays.asList(network1, network2);
+
+        // Act #1
+        heatbridge.buildAddNetworksToAaiAction(vnfId, vfModuleId, networks);
+
+        // Assert #1
+        verify(transaction, times(2)).createIfNotExists(any(AAIResourceUri.class), any(Optional.class));
+
+        // Act #2
+        heatbridge.buildAddNetworksToAaiAction(vnfId, vfModuleId, networks);
+
+        // Assert #2
+        verify(transaction, times(4)).createIfNotExists(any(AAIResourceUri.class), any(Optional.class));
+
+    }
+
     @Test
     public void testUpdateVserverLInterfacesToAai_skipVlans() throws HeatBridgeException {
         // Arrange