Policy exclusions & parallel netconf transactions
[groupbasedpolicy.git] / renderers / vpp / src / main / java / org / opendaylight / groupbasedpolicy / renderer / vpp / lisp / flat / overlay / FlatOverlayManager.java
index 24c6d8bed0f452c7773d09474025c61207741feb..b7433c20970676f84bb7b2cf785bff6d4cd8673d 100644 (file)
@@ -9,18 +9,26 @@
 package org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.flat.overlay;
 
 
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
+import javax.annotation.Nonnull;
+
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.StaticArpCommand;
-import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.mappers.HostIdToMetadataInterfaceMapper;
-import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.mappers.HostVrfRoutingInformationMapper;
-import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.mappers.InterfaceNameToStaticInfoMapper;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.info.container.EndpointHost;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.info.container.HostRelatedInfoContainer;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.info.container.states.PhysicalInterfaces;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.info.container.states.PortInterfaces;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.info.container.states.PortRouteState;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.info.container.states.SubnetState;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.info.container.states.VrfHolder;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.info.container.states.VrfState;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.mappers.NeutronTenantToVniMapper;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.util.ConfigManagerHelper;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.util.Constants;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.util.IpAddressUtil;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.GbpNetconfTransaction;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.General;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.LispUtil;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.MountedDataBrokerProvider;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.VppIidFactory;
 import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
@@ -39,7 +47,8 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import javax.annotation.Nonnull;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
 
 /**
  * Created by Shakib Ahmed on 5/2/17.
@@ -51,23 +60,19 @@ public class FlatOverlayManager {
     private DataBroker dataBroker;
 
     private NeutronTenantToVniMapper neutronTenantToVniMapper = NeutronTenantToVniMapper.getInstance();
-    private HostVrfRoutingInformationMapper hostVrfInfo = HostVrfRoutingInformationMapper.getInstance();
-    private HostIdToMetadataInterfaceMapper
-            hostIdToMetadataInterfaceMapper = HostIdToMetadataInterfaceMapper.getInstance();
-
-    private InterfaceNameToStaticInfoMapper interfaceNameToStaticInfoMapper;
+    private HostRelatedInfoContainer hostRelatedInfoContainer = HostRelatedInfoContainer.getInstance();
 
     private StaticRoutingHelper staticRoutingHelper;
 
-    public FlatOverlayManager(@Nonnull DataBroker dataBroker, @Nonnull MountedDataBrokerProvider mountedDataBrokerProvider) {
+    public FlatOverlayManager(@Nonnull DataBroker dataBroker,
+                              @Nonnull MountedDataBrokerProvider mountedDataBrokerProvider) {
         this.overlayHelper = new ConfigManagerHelper(mountedDataBrokerProvider);
-        this.interfaceNameToStaticInfoMapper = InterfaceNameToStaticInfoMapper.getInstance();
-        staticRoutingHelper = new StaticRoutingHelper(interfaceNameToStaticInfoMapper);
+        staticRoutingHelper = new StaticRoutingHelper();
         this.dataBroker = dataBroker;
     }
 
     public void configureEndpointForFlatOverlay(AddressEndpointWithLocation addressEp) {
-        if (!overlayHelper.isMetadataPort(addressEp)) {
+        if (!overlayHelper.hasRelativeLocations(addressEp)) {
             configureInterfaceForFlatOverlay(addressEp);
             addStaticArp(addressEp);
             addStaticRoute(addressEp);
@@ -80,13 +85,17 @@ public class FlatOverlayManager {
 
                 long vrf = getVni(addressEp.getTenant().getValue());
 
-                if (!hostIdToMetadataInterfaceMapper.isMetadataInterfaceConfigured(hostName, metadataInterfaceName)) {
-                    DataBroker vppDataBroker = overlayHelper.getPotentialExternalDataBroker(externalLocation).get();
-                    addInterfaceInVrf(vppDataBroker, metadataInterfaceName, vrf);
+                String metadataSubnetUuid = Constants.METADATA_SUBNET_UUID;
+
+                PortInterfaces portInterfacesOfHost = hostRelatedInfoContainer.getPortInterfaceStateOfHost(hostName);
+
+                if (!portInterfacesOfHost.isInterfaceConfiguredForMetadata(metadataInterfaceName)) {
+                    addInterfaceInVrf(hostName, metadataInterfaceName, vrf);
                     String physicalAddress = resolvePhysicalAddress(hostName, metadataInterfaceName);
-                    addStaticArp(vppDataBroker, hostName, metadataInterfaceName, physicalAddress, metadataIp);
-                    addStaticRoute(vppDataBroker, hostName, vrf, metadataIp, metadataIpPrefix, metadataInterfaceName);
-                    hostIdToMetadataInterfaceMapper.addMetadataInterfaceInHost(hostName, metadataInterfaceName);
+                    addStaticArp(hostName, metadataInterfaceName, physicalAddress, metadataIp);
+                    addStaticRoute(hostName, vrf, metadataSubnetUuid, metadataIp, metadataIpPrefix,
+                            metadataInterfaceName);
+                    portInterfacesOfHost.addInterfaceInMetadataInterfaceSet(metadataInterfaceName);
                 }
             });
         }
@@ -118,43 +127,66 @@ public class FlatOverlayManager {
     }
 
     public void handleEndpointDeleteForFlatOverlay(AddressEndpointWithLocation addressEp) {
+        if (overlayHelper.hasRelativeLocations(addressEp)) {
+            // okay to ignore
+            // routes will be deleted on interface delete
+            return;
+        }
         deleteStaticRoute(addressEp);
     }
 
+    public void handleInterfaceDeleteForFlatOverlay(DataBroker vppDataBroker, VppEndpoint vppEndpoint) {
+        String hostName = vppEndpoint.getVppNodeId().getValue();
+        String interfaceName = vppEndpoint.getVppInterfaceName();
+
+        staticRoutingHelper.deleteAllRoutesThroughInterface(vppDataBroker, hostName, interfaceName);
+
+        PortInterfaces portInterfaces = hostRelatedInfoContainer.getPortInterfaceStateOfHost(hostName);
+        portInterfaces.removePortInterface(interfaceName);
+    }
+
     private void configureInterfaceForFlatOverlay(AddressEndpointWithLocation addressEp) {
         addInterfaceInVrf(addressEp);
     }
 
     private void addInterfaceInVrf(AddressEndpointWithLocation addressEp) {
-        DataBroker vppDataBroker = overlayHelper.getPotentialExternalDataBroker(addressEp).get();
+        EndpointHost endpointHost = overlayHelper.getEndpointHostInformation(addressEp);
         long vni = getVni(addressEp.getTenant().getValue());
         long vrf = vni;
         Optional<String> interfaceNameOptional = overlayHelper.getInterfaceName(addressEp);
 
         Preconditions.checkArgument(interfaceNameOptional.isPresent());
 
-        addInterfaceInVrf(vppDataBroker, interfaceNameOptional.get(), vrf);
+        addInterfaceInVrf(endpointHost.getHostName(), interfaceNameOptional.get(), vrf);
     }
 
-    private void addInterfaceInVrf(DataBroker vppDataBroker, String interfaceName, long vrf) {
-        if (!putVrfInInterface(vppDataBroker, interfaceName, vrf)) {
+    private void addInterfaceInVrf(String hostName, String interfaceName, long vrf) {
+        if (hostRelatedInfoContainer.getPortInterfaceStateOfHost(hostName)
+                .isVrfConfiguredForInterface(interfaceName)) {
+            return;
+        }
+
+        if (!putVrfInInterface(hostName, interfaceName, vrf)) {
             LOG.warn("Failed to put interface {} to vrf {}", interfaceName, vrf);
         } else {
+            hostRelatedInfoContainer
+                    .getPortInterfaceStateOfHost(hostName)
+                    .initializeRoutingContextForInterface(interfaceName, vrf);
             LOG.debug("Added interface {} to vrf {}", interfaceName, vrf);
         }
     }
 
-    private boolean putVrfInInterface(DataBroker vppDataBroker,
+    private boolean putVrfInInterface(String hostName,
                                   String interfaceName,
                                   Long vrf) {
         InstanceIdentifier<Routing> iid = VppIidFactory.getRoutingIid(new InterfaceKey(interfaceName));
         RoutingBuilder builder = new RoutingBuilder();
         builder.setIpv4VrfId(vrf);
-        return GbpNetconfTransaction.netconfSyncedWrite(vppDataBroker, iid, builder.build(), GbpNetconfTransaction.RETRY_COUNT);
+        return GbpNetconfTransaction.netconfSyncedWrite(LispUtil.HOSTNAME_TO_IID.apply(hostName), iid,
+                builder.build(), GbpNetconfTransaction.RETRY_COUNT);
     }
 
     private void addStaticArp(AddressEndpointWithLocation addressEp) {
-        DataBroker vppDataBroker = overlayHelper.getPotentialExternalDataBroker(addressEp).get();
         String hostName = overlayHelper.getHostName(addressEp).get();
         String physicalAddress = overlayHelper.getPhysicalAddress(addressEp);
         Optional<String> interfaceNameOptional = overlayHelper.getInterfaceName(addressEp);
@@ -163,17 +195,16 @@ public class FlatOverlayManager {
 
         String interfaceName = interfaceNameOptional.get();
 
-        addStaticArp(vppDataBroker, hostName, interfaceName, physicalAddress, overlayHelper.getInterfaceIp(addressEp));
+        addStaticArp(hostName, interfaceName, physicalAddress, overlayHelper.getInterfaceIp(addressEp));
     }
 
-    private void addStaticArp(DataBroker vppDataBroker,
-                              String hostName,
+    private void addStaticArp(String hostName,
                               String interfaceName,
                               String physicalAddress,
                               Ipv4Address ipv4Address) {
         Ipv4AddressNoZone ip = new Ipv4AddressNoZone(ipv4Address);
         InterfaceKey interfaceKey = new InterfaceKey(interfaceName);
-        if (!putStaticArp(vppDataBroker,
+        if (!putStaticArp(hostName,
                              interfaceKey,
                              new PhysAddress(physicalAddress),
                              ip)) {
@@ -185,7 +216,7 @@ public class FlatOverlayManager {
         }
     }
 
-    private boolean putStaticArp(DataBroker vppDataBroker,
+    private boolean putStaticArp(String hostName,
                                  InterfaceKey interfaceKey,
                                  PhysAddress physAddress,
                                  Ipv4AddressNoZone ip) {
@@ -196,76 +227,123 @@ public class FlatOverlayManager {
         staticArpCommandBuilder.setIp(ip);
         staticArpCommandBuilder.setLinkLayerAddress(physAddress);
 
-        return GbpNetconfTransaction.netconfSyncedWrite(vppDataBroker,
+        return GbpNetconfTransaction.netconfSyncedWrite(LispUtil.HOSTNAME_TO_IID.apply(hostName),
                 staticArpCommandBuilder.build(), GbpNetconfTransaction.RETRY_COUNT);
     }
 
     private void addStaticRoute(AddressEndpointWithLocation addressEp) {
-        DataBroker vppDataBroker = overlayHelper.getPotentialExternalDataBroker(addressEp).get();
         String hostName = overlayHelper.getHostName(addressEp).get();
-
         long vni = getVni(addressEp.getTenant().getValue());
         long vrf = vni;
 
+        String portSubnetUuid = overlayHelper.getSubnet(addressEp);
+
         String outgoingInterfaceName = overlayHelper.getInterfaceName(addressEp).get();
         Ipv4Address ipWithoutPrefix = overlayHelper.getInterfaceIp(addressEp);
+
+        if (overlayHelper.isMetadataPort(addressEp)) {
+            //override original port subnet to handle the Absolute location case of address endpoint
+            portSubnetUuid = Constants.METADATA_SUBNET_UUID;
+        }
+
         Ipv4Prefix ipv4Prefix = overlayHelper.getInterfaceIpAsPrefix(addressEp);
 
-        addStaticRoute(vppDataBroker, hostName, vrf, ipWithoutPrefix, ipv4Prefix, outgoingInterfaceName);
+        addStaticRoute(hostName, vrf, portSubnetUuid, ipWithoutPrefix, ipv4Prefix, outgoingInterfaceName);
     }
 
-    private void addStaticRoute(DataBroker vppDataBroker, String hostName, long vrf, Ipv4Address ipWithoutPrefix,
-                                Ipv4Prefix ipv4Prefix, String outgoingInterfaceName) {
+    private void addStaticRoute(String hostName, long vrfId, String hostIpSubnetUuid,
+                                Ipv4Address ipWithoutPrefix, Ipv4Prefix ipv4Prefix, String outgoingInterfaceName) {
 
-        if (!hostVrfInfo.vrfExists(hostName, vrf)) {
-            if (!staticRoutingHelper.addRoutingProtocolForVrf(vppDataBroker, hostName, vrf)) {
-                LOG.warn("Failed to add Routing protocol for host {} and vrf {}!", hostName, vrf);
+        VrfHolder vrfHolderOfHost = hostRelatedInfoContainer.getVrfStateOfHost(hostName);
+
+        if (!vrfHolderOfHost.hasVrf(vrfId)) {
+            if (!staticRoutingHelper.addRoutingProtocolForVrf(LispUtil.HOSTNAME_TO_IID.apply(hostName), vrfId,
+                    vrfHolderOfHost)) {
+                addStaticRouteToPublicInterface(hostName, vrfId);
+                LOG.warn("Failed to add Routing protocol for host {} and vrf {}!", hostName, vrfId);
             }
         }
 
-        if (staticRoutingHelper.endPointRoutingExists(outgoingInterfaceName, ipWithoutPrefix)) {
-            return;
-        }
+        VrfState vrfStateOfVrfId = vrfHolderOfHost.getVrfState(vrfId);
 
-        if (staticRoutingHelper.routeAlreadyExistsInHostVrf(hostName, vrf, ipWithoutPrefix)) {
-            LOG.warn("Ip already exists in host {} vrf {} ip {}", hostName, vrf, ipWithoutPrefix);
+        if (vrfStateOfVrfId.getSubnetHolder().getSubnetState(hostIpSubnetUuid).isIpPresent(ipWithoutPrefix)) {
+            LOG.info("Ip already exists in host {} vrf {} ip {}", hostName, vrfId, ipWithoutPrefix);
             return;
         }
 
-        if (!staticRoutingHelper.addSingleStaticRouteInRoutingProtocol(vppDataBroker,
-                hostName,
-                vrf,
-                ipWithoutPrefix,
-                ipv4Prefix,
-                outgoingInterfaceName)) {
+        if (!staticRoutingHelper.addSingleStaticRouteInRoutingProtocol(hostName, vrfId, hostIpSubnetUuid,
+                ipWithoutPrefix, ipv4Prefix, outgoingInterfaceName)) {
             LOG.warn("Failed to add routing ({} via {}) in vrf {} in compute host {}!",
-                    ipv4Prefix, outgoingInterfaceName, vrf, hostName);
+                    ipv4Prefix, outgoingInterfaceName, vrfId, hostName);
         } else {
             LOG.debug("Added route ({} via {}) in vrf {} in compute host {}",
-                    ipv4Prefix, outgoingInterfaceName, vrf, hostName);
+                    ipv4Prefix, outgoingInterfaceName, vrfId, hostName);
+        }
+    }
+
+    private void addStaticRouteToPublicInterface(String hostName, long vrfId) {
+        Ipv4Address physicalInterfaceIp = hostRelatedInfoContainer
+                .getPhysicalInterfaceState(hostName)
+                .getIp(PhysicalInterfaces.PhysicalInterfaceType.PUBLIC).getIpv4Address();
+        String physicalInterfaceName = hostRelatedInfoContainer
+                .getPhysicalInterfaceState(hostName)
+                .getName(PhysicalInterfaces.PhysicalInterfaceType.PUBLIC);
+        if (physicalInterfaceName != null && !physicalInterfaceName.isEmpty()) {
+            if (!staticRoutingHelper.addSingleStaticRouteInRoutingProtocol(hostName, vrfId,
+                    Constants.PUBLIC_SUBNET_UUID, physicalInterfaceIp,
+                    IpAddressUtil.toIpV4Prefix(physicalInterfaceIp), physicalInterfaceName)) {
+                LOG.warn("Failed to add route for physical interface in vrf {} compute host {}", vrfId, hostName);
+            } else {
+                LOG.debug("Added route for physical interface {} in vrf {}", physicalInterfaceName, vrfId);
+            }
         }
     }
 
     private void deleteStaticRoute(AddressEndpointWithLocation addressEp) {
-        DataBroker vppDataBroker = overlayHelper.getPotentialExternalDataBroker(addressEp).get();
         String hostName = overlayHelper.getHostName(addressEp).get();
         String interfaceName = overlayHelper.getInterfaceName(addressEp).get();
 
         long vni = getVni(addressEp.getTenant().getValue());
-        long vrf = vni;
+        long vrfId = vni;
+
+        String ipSubnetUuid = overlayHelper.getSubnet(addressEp);
+
+        if (overlayHelper.isMetadataPort(addressEp)) {
+            //override original port subnet to handle the Absolute location case of address endpoint
+            ipSubnetUuid = Constants.METADATA_SUBNET_UUID;
+        }
 
         Ipv4Address ipWithoutPrefix = overlayHelper.getInterfaceIp(addressEp);
 
-        if (!staticRoutingHelper.deleteSingleStaticRouteFromRoutingProtocol(vppDataBroker,
-                                                                       hostName,
-                                                                       vrf,
-                                                                       interfaceName)) {
+        PortRouteState portRouteState = hostRelatedInfoContainer
+                                            .getPortInterfaceStateOfHost(hostName)
+                                            .getPortRouteState(interfaceName);
+
+        SubnetState subnetState = hostRelatedInfoContainer
+                                    .getVrfStateOfHost(hostName)
+                                    .getVrfState(vrfId)
+                                    .getSubnetHolder()
+                                    .getSubnetState(ipSubnetUuid);
+
+        if (!subnetState.isIpPresent(ipWithoutPrefix)) {
+            LOG.debug("Route {} already deleted from vrf {} of host {}", ipWithoutPrefix, vrfId, hostName);
+            return;
+        }
+
+        long targetRouteId = portRouteState.getRouteIdOfIp(ipWithoutPrefix);
+
+        if (!staticRoutingHelper.deleteSingleStaticRouteFromRoutingProtocol(hostName,
+                                                                            vrfId,
+                                                                            interfaceName,
+                                                                            targetRouteId)) {
             LOG.warn("Failed to delete route ({} via {}) from vrf {} from host{}",
-                    ipWithoutPrefix, interfaceName, vrf, hostName);
+                    ipWithoutPrefix, interfaceName, vrfId, hostName);
 
         } else {
+            portRouteState.removeIp(ipWithoutPrefix);
+            subnetState.removeIp(ipWithoutPrefix);
             LOG.debug("Delete Static Route ({} via {}) from vrf {} from host {}",
-                    ipWithoutPrefix, interfaceName, vrf, hostName);
+                    ipWithoutPrefix, interfaceName, vrfId, hostName);
         }
     }