Support for metadata in HA 54/57754/15
authorTomas Cechvala <tcechval@cisco.com>
Thu, 11 May 2017 15:30:45 +0000 (17:30 +0200)
committerTomas Cechvala <tcechval@cisco.com>
Fri, 2 Jun 2017 14:53:16 +0000 (16:53 +0200)
Metadata service in Openstack is reachable through every DHCP
port that is created in HA scenarios. This requires severe
changes in current forwarding design. First, Metadata is
registered as an endpoint, and since in HA it is reachable
through multiple local ports, it is assigned relative location
that is available in current models.

TODO extend forwarding APIs for this use case

Change-Id: I097f66eb04da8419a5d6dd551ad4c28f6185efb4
Signed-off-by: Tomas Cechvala <tcechval@cisco.com>
16 files changed:
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/RendererConfigurationBuilder.java
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/RendererManager.java
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/RendererUtils.java
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/util/AddressEndpointUtils.java
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/util/EndpointLocationUtils.java
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/util/EndpointUtils.java
neutron-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/mapper/mapping/NeutronPortAware.java
neutron-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/mapper/mapping/NeutronRouterAware.java
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/iface/InterfaceManager.java
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/iface/VppEndpointLocationProvider.java
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/ForwardingManager.java
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/PolicyContext.java
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/VppRendererPolicyManager.java
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/acl/AclManager.java
renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/iface/VppEndpointLocationProviderTest.java
renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/VppRendererPolicyManagerTest.java

index a7ce6b192b10afa23099c8231e182a02d9682daf..c492f2256f0ad005690fd9f5caaad47eab3cc6bf 100644 (file)
@@ -314,6 +314,17 @@ public class RendererConfigurationBuilder {
         if (potentialAbsNodeLoc.isPresent()) {
             return rendererByNode.get(potentialAbsNodeLoc.get());
         }
+        else {
+            Optional<List<InstanceIdentifier<?>>> potentianRelativeLocation =
+                    EndpointLocationUtils.resolveRelativeExternalNodeMountPointLocation(epLoc);
+            if (potentianRelativeLocation.isPresent()) {
+                RendererName rn = null;
+                for (InstanceIdentifier<?> iid : potentianRelativeLocation.get()) {
+                    rn = rendererByNode.get(iid);
+                }
+                return rn;
+            }
+        }
         return null;
     }
 
index baaf223797c8ec2a5e33bad912cb1f49f6b2fa48..1a57f6fa814ea1c4a9c1a918ff521fde2abf0d58 100644 (file)
@@ -388,6 +388,10 @@ public class RendererManager implements AutoCloseable {
     @VisibleForTesting
     void resolveRendererConfigForEndpoint(AddressEndpoint rendererAdrEp,
                                           RendererConfigurationBuilder rendererPolicyBuilder) {
+        List<EndpointGroupId> epgIds = rendererAdrEp.getEndpointGroup();
+        if (epgIds == null || epgIds.contains(RendererUtils.EPG_EXTERNAL_ID)) {
+            return;
+        }
         Set<EpgKeyDto> rendererEpgs = toEpgKeys(rendererAdrEp.getEndpointGroup(), rendererAdrEp.getTenant());
         RendererEndpointKey rendererEpKey = AddressEndpointUtils.toRendererEpKey(rendererAdrEp.getKey());
         for (EpgKeyDto rendererEpg : rendererEpgs) {
@@ -481,8 +485,10 @@ public class RendererManager implements AutoCloseable {
                     }
                 }
             } else {
-                if (!currentState.epLocInfo.hasAbsoluteLocation(peerAdrEpKey)) {
-                    LOG.debug("Peer does not have absolute location therefore it is ignored: {}", peerAdrEpKey);
+                if (!currentState.epLocInfo.hasAbsoluteLocation(peerAdrEpKey)
+                        && !currentState.epLocInfo.hasRelativeLocation(peerAdrEpKey)) {
+                    LOG.debug("Peer does not have absolute nor relative location therefore it is ignored: {}",
+                            peerAdrEpKey);
                     continue;
                 }
                 PeerEndpointKey peerEpKey = AddressEndpointUtils.toPeerEpKey(peerAdrEpKey);
index fc24581ed421cb70ad953f7aadcdfcd52899c298..a54f2a5da04ccd8e05b99fa32fafae60f694ac0c 100644 (file)
@@ -13,6 +13,7 @@ import java.util.List;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.RendererName;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.Renderer;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.nodes.RendererNode;
@@ -25,6 +26,8 @@ import com.google.common.collect.Maps;
 
 public class RendererUtils {
 
+    public static final EndpointGroupId EPG_EXTERNAL_ID = new EndpointGroupId("eeeaa3a2-e9ba-44e0-a462-bea923d30e38");
+
     public static @Nonnull ImmutableMultimap<InstanceIdentifier<?>, RendererName> resolveRenderersByNodes(
             @Nullable List<Renderer> renderers) {
         if (renderers == null) {
index 623ff8ab5c03f0f783e36c1eb0bafc70d282104a..c07a1355b269b49382acb75606efe57d6a4e398b 100644 (file)
@@ -8,17 +8,26 @@
 
 package org.opendaylight.groupbasedpolicy.renderer.util;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Optional;
+import java.util.function.Predicate;
 
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpointKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.AbsoluteLocation;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.LocationType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.location.type.ExternalLocationCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.relative.location.relative.locations.ExternalLocation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.relative.location.relative.locations.ExternalLocationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.parent.endpoint._case.ParentEndpointKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocation;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocationKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.RendererEndpointKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.renderer.endpoint.PeerEndpointKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.renderer.endpoint.PeerExternalEndpointKey;
 
+import com.google.common.base.Function;
+
 public class AddressEndpointUtils {
 
     public static RendererEndpointKey toRendererEpKey(AddressEndpointKey rendererAdrEpKey) {
@@ -55,24 +64,63 @@ public class AddressEndpointUtils {
                 peerExtEpKey.getContextId(), peerExtEpKey.getContextType());
     }
 
-    /**
-     * Compares absolute external locations of address end-points in the arguments.
-     */
-    public static boolean sameExternalLocationCase(AddressEndpointWithLocation ae0, AddressEndpointWithLocation ae1) {
-        if (ae0.getAbsoluteLocation() == null || ae1.getAbsoluteLocation() == null) {
+    public static AddressEndpointKey fromParentEndpointKey(ParentEndpointKey key) {
+        return new AddressEndpointKey(key.getAddress(), key.getAddressType(),
+                key.getContextId(), key.getContextType());
+    }
+
+    public static boolean sameExternalLocationCase(AddressEndpointWithLocation ref, AddressEndpointWithLocation ae1) {
+        if (ref.getRelativeLocations() != null || ref.getAbsoluteLocation() == null) {
             return false;
         }
-        Optional<LocationType> loc0Type = Optional.ofNullable(ae0.getAbsoluteLocation().getLocationType());
-        Optional<LocationType> loc1Type = Optional.ofNullable(ae1.getAbsoluteLocation().getLocationType());
-        if (!(loc0Type.isPresent() && loc0Type.get() instanceof ExternalLocationCase)
-                || !(loc1Type.isPresent() && loc1Type.get() instanceof ExternalLocationCase)) {
+        Function<AbsoluteLocation, Optional<ExternalLocation>> absoluteToExternal =
+                new Function<AbsoluteLocation, Optional<ExternalLocation>>() {
+
+                    @Override
+                    public Optional<ExternalLocation> apply(AbsoluteLocation absoluteLocation) {
+                        if (absoluteLocation == null || absoluteLocation.getLocationType() == null) {
+                            return Optional.empty();
+                        }
+                        Optional<LocationType> locationType = Optional.ofNullable(absoluteLocation.getLocationType());
+                        if (locationType.isPresent() && locationType.get() instanceof ExternalLocationCase) {
+                            ExternalLocationCase extLocCase = (ExternalLocationCase) absoluteLocation.getLocationType();
+                            return Optional.of(new ExternalLocationBuilder()
+                                .setExternalNodeMountPoint(extLocCase.getExternalNodeMountPoint())
+                                .setExternalNodeConnector(extLocCase.getExternalNodeConnector())
+                                .build());
+                        }
+                        return Optional.empty();
+                    }
+                };
+        Optional<ExternalLocation> refLoc0 = absoluteToExternal.apply(ref.getAbsoluteLocation());
+        if (!refLoc0.isPresent()) {
             return false;
         }
-        ExternalLocationCase loc0 = (ExternalLocationCase) loc0Type.get();
-        ExternalLocationCase loc1 = (ExternalLocationCase) loc1Type.get();
-        return (loc0.getExternalNodeMountPoint() == null || loc1.getExternalNodeMountPoint() == null
-                || loc0.getExternalNodeConnector() == null || loc1.getExternalNodeConnector() == null) ? false : loc0
-                    .getExternalNodeMountPoint().toString().equals(loc1.getExternalNodeMountPoint().toString())
-                        && loc0.getExternalNodeConnector().equals(loc1.getExternalNodeConnector());
+        Predicate<ExternalLocation> sameLocation = new Predicate<ExternalLocation>() {
+
+            @Override
+            public boolean test(ExternalLocation loc1) {
+                boolean valuesPresent = refLoc0.get().getExternalNodeMountPoint() == null
+                        || loc1.getExternalNodeMountPoint() == null
+                        || refLoc0.get().getExternalNodeConnector() == null
+                        || loc1.getExternalNodeConnector() == null;
+                return (valuesPresent) ? false : refLoc0.get()
+                    .getExternalNodeMountPoint()
+                    .toString()
+                    .equals(loc1.getExternalNodeMountPoint().toString())
+                        && refLoc0.get().getExternalNodeConnector().equals(loc1.getExternalNodeConnector());
+            }
+        };
+        List<ExternalLocation> extLocs = new ArrayList<>();
+        Optional<ExternalLocation> refLoc1 = absoluteToExternal.apply(ae1.getAbsoluteLocation());
+        if (refLoc1.isPresent()) {
+            extLocs.add(refLoc1.get());
+        } else if (ae1.getRelativeLocations() != null && ae1.getRelativeLocations().getExternalLocation() != null) {
+            extLocs.addAll(ae1.getRelativeLocations().getExternalLocation());
+        }
+        if (extLocs.stream().filter(sameLocation).findAny().isPresent()) {
+            return true;
+        }
+        return false;
     }
 }
index 89478204908805d54a41a344f88601d598153916..13dd62560b1f149e868a3b3323e571e009d472bd 100644 (file)
@@ -9,6 +9,7 @@
 package org.opendaylight.groupbasedpolicy.renderer.util;
 
 import java.util.List;
+import java.util.stream.Collectors;
 
 import javax.annotation.Nullable;
 
@@ -17,6 +18,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpo
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.LocationType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.location.type.ExternalLocationCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.location.type.InternalLocationCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.relative.location.RelativeLocations;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
 import com.google.common.base.Optional;
@@ -44,6 +46,15 @@ public class EndpointLocationUtils {
                 if (potentialAbsExtNodeMpLocation.isPresent()) {
                     resultBuilder.put(potentialAbsExtNodeMpLocation.get(), epLoc);
                 }
+                else {
+                    Optional<List<InstanceIdentifier<?>>> potentialRelExtNodeMpLocation =
+                            resolveRelativeExternalNodeMountPointLocation(epLoc);
+                    if(potentialRelExtNodeMpLocation.isPresent()) {
+                        for(InstanceIdentifier<?> iid : potentialRelExtNodeMpLocation.get()) {
+                            resultBuilder.put(iid,epLoc);
+                        }
+                    }
+                }
             }
         }
         return resultBuilder.build();
@@ -78,6 +89,19 @@ public class EndpointLocationUtils {
         return Optional.absent();
     }
 
+    public static Optional<List<InstanceIdentifier<?>>> resolveRelativeExternalNodeMountPointLocation(
+            AddressEndpointLocation epLoc) {
+        RelativeLocations relativeLocations = epLoc.getRelativeLocations();
+        if (relativeLocations != null) {
+            List<InstanceIdentifier<?>> collect = relativeLocations.getExternalLocation()
+                .stream()
+                .map(l -> l.getExternalNodeMountPoint())
+                .collect(Collectors.toList());
+            return (collect.isEmpty()) ? Optional.absent() : Optional.of(collect);
+        }
+        return Optional.absent();
+    }
+
     public static Optional<InstanceIdentifier<?>> resolveAbsoluteNodeLocation(AddressEndpointLocation epLoc) {
         if (epLoc.getAbsoluteLocation() == null) {
             return Optional.absent();
index 909f69599ef54cfa55ddb13798179769b6cbcecd..dd60cab670c17d7f0af535d4e74afdc3a423d34d 100644 (file)
@@ -76,6 +76,9 @@ public class EndpointUtils {
     public static boolean isExternalEndpoint(@Nonnull DataBroker dataBroker, @Nonnull AddressEndpoint addrEp) {
         ReadOnlyTransaction rTx = dataBroker.newReadOnlyTransaction();
         List<ListenableFuture<Boolean>> results = new ArrayList<>();
+        if(addrEp.getEndpointGroup() == null) {
+            return false;
+        }
         for (EndpointGroupId epgId : addrEp.getEndpointGroup()) {
             results.add(Futures.transform(
                     rTx.read(LogicalDatastoreType.CONFIGURATION,
index f9550d7bc78c877fa251167a44d756b5ae6c67ef..b80b9f6f1b1ddcfbb0cd369889a376743f78faf9 100644 (file)
@@ -42,6 +42,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpo
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.UnregisterEndpointInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.NetworkContainmentBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.network.containment.containment.NetworkDomainContainmentBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpoint;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpointKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.child.endpoints.ChildEndpoint;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.child.endpoints.ChildEndpointBuilder;
@@ -130,12 +131,10 @@ public class NeutronPortAware implements NeutronAware<Port> {
             FixedIps portIpWithSubnet = potentialPortIpWithSubnet.get();
             ContextId routerL3Context = new ContextId(port.getDeviceId());
             ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
-
             AddressEndpointKey addrEpKey = new AddressEndpointKey(port.getMacAddress().getValue(),
                 MacAddressType.class, new ContextId(port.getNetworkId().getValue()), MappingUtils.L2_BRDIGE_DOMAIN);
             UniqueId portId = new UniqueId(port.getUuid().getValue());
             addBaseEndpointMappings(addrEpKey, portId, rwTx);
-
             // Add Qrouter and VPProuter port as Endpoint
             if (port.getAugmentation(PortBindingExtension.class) != null &&
                 PortUtils.DEVICE_VIF_TYPE.equals(port.getAugmentation(PortBindingExtension.class).getVifType())) {
@@ -145,19 +144,16 @@ public class NeutronPortAware implements NeutronAware<Port> {
                     LOG.warn("QRouter port does not have an IP address. {}", port);
                     return;
                 }
-
                 FixedIps ipWithSubnet = firstFixedIps.get();
                 NetworkDomainId networkContainment = new NetworkDomainId(ipWithSubnet.getSubnetId().getValue());
                 List<EndpointGroupId> epgsFromSecGroups = resolveEpgIdsFromSecGroups(port.getSecurityGroups());
                 epgsFromSecGroups.add(NetworkService.EPG_ID);
-
                 // BUILD BASE ENDPOINT
                 AddressEndpointRegBuilder l2BaseEp = createBasicMacAddrEpInputBuilder(port, networkContainment,
                     epgsFromSecGroups);
                 AddressEndpointRegBuilder l3BaseEp = createBasicL3AddrEpInputBuilder(port, networkContainment,
                     epgsFromSecGroups, neutron);
                 setParentChildRelationshipForEndpoints(l3BaseEp, l2BaseEp);
-
                 // BUILD ENDPOINT
                 org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInputBuilder
                     epInBuilder =
@@ -167,7 +163,6 @@ public class NeutronPortAware implements NeutronAware<Port> {
                     ImmutableList.of(l2BaseEp.build(), l3BaseEp.build()), port, rwTx, addBaseEpMapping);
                 registerEndpointAndStoreMapping(epInBuilder.build(), port, rwTx);
             }
-
             // change L3Context for all EPs with same subnet as router port
             changeL3ContextForEpsInSubnet(portIpWithSubnet.getSubnetId(), neutron);
             // set L3Context as parent for bridge domain which is parent of subnet
@@ -211,20 +206,25 @@ public class NeutronPortAware implements NeutronAware<Port> {
                     epgsFromSecGroups, neutron);
 
             setParentChildRelationshipForEndpoints(l3BaseEp, l2BaseEp);
-
             org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInputBuilder epInBuilder = createEndpointRegFromPort(
                     port, ipWithSubnet, networkContainment, epgsFromSecGroups, neutron);
-
             ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
             registerBaseEndpointAndStoreMapping(
-                    ImmutableList.of(l2BaseEp.build(), l3BaseEp.build()), port, rwTx, addBaseEpMapping);
+                    ImmutableList.of(l3BaseEp.build(), l2BaseEp.build()), port, rwTx, addBaseEpMapping);
 
             AddressEndpointRegBuilder metadataEp = createBasicL3AddrEpInputBuilder(cloneMetadataPortFromDhcpPort(port, metadataIpPrefix), networkContainment,
                     Lists.newArrayList(MetadataService.EPG_ID), neutron);
-            setParentChildRelationshipForEndpoints(metadataEp, l2BaseEp);
+            AddressEndpointKey aek = new AddressEndpointKey(metadataEp.getAddress(), metadataEp.getAddressType(), metadataEp.getContextId(), metadataEp.getContextType());
+            Optional<AddressEndpoint> optMetadataEp = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL, IidFactory.addressEndpointIid(aek), rwTx);
+            if(!optMetadataEp.isPresent()) {
+                setParentChildRelationshipForEndpoints(metadataEp, l2BaseEp);
+            } else {
+                List<ChildEndpoint> childs = optMetadataEp.get().getChildEndpoint();
+                childs.add(createChildEndpoint(l2BaseEp));
+                metadataEp.setChildEndpoint(childs);
+            }
             registerBaseEndpointAndStoreMapping(
                     ImmutableList.of(metadataEp.build()), port, rwTx, true);
-
             registerEndpointAndStoreMapping(epInBuilder.build(), port, rwTx);
             DataStoreHelper.submitToDs(rwTx);
         } else if (PortUtils.isNormalPort(port)) {
index aaf1bd054c3f6f15ff21cc7599321b0aa55a7ca7..bcfd641f4d4951fbad4b3de38c0513c4f53750a8 100644 (file)
@@ -232,8 +232,9 @@ public class NeutronRouterAware implements NeutronAware<Router> {
         addrEpBuilder.setContextId(routerl3ContextId);
         addrEpBuilder.setContextType(MappingUtils.L3_CONTEXT);
         addrEpBuilder.setTenant(tenantId);
-        addrEpBuilder.setNetworkContainment(new NetworkContainmentBuilder().setContainment(
-                new NetworkDomainContainmentBuilder().setNetworkDomainId(networkDomainId).build()).build());
+        addrEpBuilder
+            .setNetworkContainment(new NetworkContainmentBuilder().setContainment(new NetworkDomainContainmentBuilder()
+                .setNetworkDomainId(networkDomainId).setNetworkDomainType(MappingUtils.SUBNET).build()).build());
         addrEpBuilder.setEndpointGroup(ImmutableList.of(MappingUtils.EPG_EXTERNAL_ID));
         addrEpBuilder.setTimestamp(System.currentTimeMillis());
         return epRegistrator.registerEndpoint(addrEpBuilder.build());
index 9b3471fcb364dd862921e0507d2aa74b2200d6a9..c4db59552a5da91f29a08cbc8e1e040846211038 100644 (file)
@@ -38,6 +38,7 @@ import org.opendaylight.groupbasedpolicy.renderer.vpp.util.VppIidFactory;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.VppRendererProcessingException;
 import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceBuilder;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.LocationType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.location.type.ExternalLocationCase;
@@ -264,17 +265,19 @@ public class InterfaceManager implements AutoCloseable {
         return deleteIfaceOnVpp(ifaceWithoutBdCommand, vppDataBroker, vppEndpoint, vppNodeIid);
     }
 
-    private ListenableFuture<Void> deleteIfaceOnVpp(ConfigCommand deleteIfaceWithoutBdCommand,
-            DataBroker vppDataBroker, VppEndpoint vppEndpoint, InstanceIdentifier<?> vppNodeIid) {
+    private ListenableFuture<Void> deleteIfaceOnVpp(ConfigCommand deleteIfaceWithoutBdCommand, DataBroker vppDataBroker,
+            VppEndpoint vppEndpoint, InstanceIdentifier<?> vppNodeIid) {
+        InterfaceBuilder intfBuilder = deleteIfaceWithoutBdCommand.getInterfaceBuilder();
         final boolean transactionState = GbpNetconfTransaction.netconfSyncedDelete(vppDataBroker,
-            deleteIfaceWithoutBdCommand, GbpNetconfTransaction.RETRY_COUNT);
+                deleteIfaceWithoutBdCommand, GbpNetconfTransaction.RETRY_COUNT);
         if (transactionState) {
             LOG.debug("Delete interface on VPP command was successful: VPP: {} Command: {}", vppNodeIid,
                     deleteIfaceWithoutBdCommand);
+            AccessListWrapper.removeAclsForInterface(vppDataBroker, new InterfaceKey(intfBuilder.getName()));
             return vppEndpointLocationProvider.deleteLocationForVppEndpoint(vppEndpoint);
         } else {
-            final String message = "Delete interface on VPP command was not successful: VPP: " + vppNodeIid +
-                    " Command: " + deleteIfaceWithoutBdCommand;
+            final String message = "Delete interface on VPP command was not successful: VPP: " + vppNodeIid
+                    " Command: " + deleteIfaceWithoutBdCommand;
             LOG.warn(message);
             return Futures.immediateFailedFuture(new VppRendererProcessingException(message));
         }
index 3a32c8978792a8a6c1d9cbe020736e8dcdad94ce..1bce842c1795333fae756ab07191cf8903823b93 100644 (file)
@@ -10,7 +10,10 @@ package org.opendaylight.groupbasedpolicy.renderer.vpp.iface;
 
 import static com.google.common.base.Preconditions.checkNotNull;
 
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ExecutionException;
 import java.util.stream.Collectors;
@@ -21,9 +24,11 @@ import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
 import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.groupbasedpolicy.renderer.util.AddressEndpointUtils;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.manager.VppNodeManager;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.CloseOnFailTransactionChain;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.KeyFactory;
@@ -32,16 +37,19 @@ import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
 import org.opendaylight.groupbasedpolicy.util.DataTreeChangeHandler;
 import org.opendaylight.groupbasedpolicy.util.EndpointUtils;
 import org.opendaylight.groupbasedpolicy.util.IidFactory;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpointKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.Endpoints;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.AddressEndpoints;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpointKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.AbsoluteLocation;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.AbsoluteLocationBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.location.type.ExternalLocationCase;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.location.type.ExternalLocationCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.child.endpoints.ChildEndpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.child.endpoints.ChildEndpointKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.relative.location.RelativeLocations;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.relative.location.RelativeLocationsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.relative.location.relative.locations.ExternalLocation;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.relative.location.relative.locations.ExternalLocationBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.parent.endpoint._case.ParentEndpoint;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.parent.endpoint._case.ParentEndpointKey;
@@ -63,6 +71,7 @@ import org.slf4j.LoggerFactory;
 
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Function;
+import com.google.common.base.Optional;
 import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
@@ -87,7 +96,6 @@ public class VppEndpointLocationProvider extends DataTreeChangeHandler<AddressEn
         WriteTransaction wTx = txChain.newWriteOnlyTransaction();
         wTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.locationProviderIid(VPP_ENDPOINT_LOCATION_PROVIDER),
                 locationProvider, true);
-
         Futures.addCallback(wTx.submit(), new FutureCallback<Void>() {
 
             @Override
@@ -167,25 +175,38 @@ public class VppEndpointLocationProvider extends DataTreeChangeHandler<AddressEn
     synchronized ListenableFuture<Void> createAbsoluteAddressEndpointLocation(VppEndpoint vppEndpoint,
             DataObjectModification<AddressEndpoint> rootNode) {
         if (vppEndpoint != null) {
+            LOG.debug("Saving VPP endpoint {}" + vppEndpoint.getKey());
             vppEndpoints.put(vppEndpoint.getKey(), vppEndpoint);
             if (cachedVppEndpoints.get(vppEndpoint.getKey()) != null) {
-                return processAddrEp(cachedVppEndpoints.get(vppEndpoint.getKey()));
+                try {
+                    processAddrEp(cachedVppEndpoints.get(vppEndpoint.getKey())).get();
+                } catch (InterruptedException | ExecutionException e) {
+                    LOG.error("Failed to resolve location for cached endpoint {}. {}", vppEndpoint.getKey(), e);
+                }
+                return Futures.immediateFuture(null);
             }
         } else if (rootNode != null) {
-            return processAddrEp(rootNode);
+            try {
+            processAddrEp(rootNode).get();
+            } catch (InterruptedException | ExecutionException e) {
+                LOG.error("Failed to resolve location for changed endpoint before={} after={}. {}",
+                        rootNode.getDataAfter(), rootNode.getDataAfter(), e);
+            }
+            return Futures.immediateFuture(null);
         }
         return Futures.immediateFuture(null);
     }
 
     private ListenableFuture<Void> processAddrEp(DataObjectModification<AddressEndpoint> rootNode) {
         if (rootNode != null) {
-            AddressEndpointChange aec = new AddressEndpointChange(rootNode, dataProvider);
+            AddressEndpointChange aec = new AddressEndpointChange(rootNode, txChain);
             switch (rootNode.getModificationType()) {
                 case WRITE:
                 case SUBTREE_MODIFIED: {
                     VppEndpoint vpp = vppEndpoints.get(vppEndpointKeyFrom(rootNode.getDataAfter().getKey()));
                     if (vpp == null) {
                         VppEndpointKey key = vppEndpointKeyFrom(rootNode.getDataAfter().getKey());
+                        LOG.debug("Caching VPP endpoint {}" + key);
                         cachedVppEndpoints.put(key, rootNode);
                         return Futures.immediateFuture(null);
                     }
@@ -268,24 +289,44 @@ public class VppEndpointLocationProvider extends DataTreeChangeHandler<AddressEn
     }
 
     public ListenableFuture<Void> replaceLocationForEndpoint(@Nonnull ExternalLocationCase location, @Nonnull AddressEndpointWithLocationKey addrEpWithLocKey) {
+        InstanceIdentifier<ProviderAddressEndpointLocation> iid = IidFactory.providerAddressEndpointLocationIid(
+                VPP_ENDPOINT_LOCATION_PROVIDER, createProviderAddressEndpointLocationKey(addrEpWithLocKey));
+        ReadOnlyTransaction rTx = dataProvider.newReadOnlyTransaction();
+        Optional<ProviderAddressEndpointLocation> optLoc = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION, iid, rTx);
+        rTx.close();
         ProviderAddressEndpointLocationKey provAddrEpLocKey =
                 KeyFactory.providerAddressEndpointLocationKey(addrEpWithLocKey);
-        AbsoluteLocation absoluteLocation =
-                new AbsoluteLocationBuilder().setLocationType(location).build();
-        ProviderAddressEndpointLocation providerAddressEndpointLocation = new ProviderAddressEndpointLocationBuilder()
-            .setKey(provAddrEpLocKey).setAbsoluteLocation(absoluteLocation).build();
+        ProviderAddressEndpointLocationBuilder builder = new ProviderAddressEndpointLocationBuilder().setKey(provAddrEpLocKey);
+        if(optLoc.isPresent() && optLoc.get().getAbsoluteLocation() != null) {
+            AbsoluteLocation absoluteLocation = optLoc.get().getAbsoluteLocation();
+            builder.setAbsoluteLocation(new AbsoluteLocationBuilder(absoluteLocation).setLocationType(location).build());
+        } else if (optLoc.isPresent() && optLoc.get().getRelativeLocations() != null) {
+            ExternalLocation extLoc = new ExternalLocationBuilder().setExternalNode(location.getExternalNode())
+            .setExternalNodeConnector(location.getExternalNodeConnector())
+            .setExternalNodeMountPoint(location.getExternalNodeMountPoint())
+            .build();
+            List<ExternalLocation> externalLocation = optLoc.get()
+                .getRelativeLocations()
+                .getExternalLocation();
+            externalLocation.add(extLoc);
+            RelativeLocations relativeLocation = new RelativeLocationsBuilder(optLoc.get().getRelativeLocations()).setExternalLocation(externalLocation).build();
+            builder.setRelativeLocations(relativeLocation);
+        }
+        else {
+            LOG.warn("Cannot replace location for endpoint {}", addrEpWithLocKey);
+            return Futures.immediateFuture(null);
+        }
+        ProviderAddressEndpointLocation providerLocation = builder.build();
         WriteTransaction wTx = txChain.newWriteOnlyTransaction();
-        wTx.put(LogicalDatastoreType.CONFIGURATION,
-                IidFactory.providerAddressEndpointLocationIid(VPP_ENDPOINT_LOCATION_PROVIDER,
-                        providerAddressEndpointLocation.getKey()),
-                providerAddressEndpointLocation);
-        LOG.debug("Updating location for {}", provAddrEpLocKey);
+        wTx.put(LogicalDatastoreType.CONFIGURATION, IidFactory.providerAddressEndpointLocationIid(
+                VPP_ENDPOINT_LOCATION_PROVIDER, providerLocation.getKey()), providerLocation);
+        LOG.debug("Updating location for {}", builder.build().getKey());
         return Futures.transform(wTx.submit(), new Function<Void, Void>() {
 
             @Override
             public Void apply(Void input) {
                 LOG.debug("{} replaced location: {}", VPP_ENDPOINT_LOCATION_PROVIDER.getValue(),
-                        providerAddressEndpointLocation);
+                        providerLocation.getKey());
                 return null;
             }
         });
@@ -301,6 +342,11 @@ public class VppEndpointLocationProvider extends DataTreeChangeHandler<AddressEn
                 key.getContextType());
     }
 
+    static ProviderAddressEndpointLocationKey createProviderAddressEndpointLocationKey(AddressEndpointWithLocationKey key) {
+        return new ProviderAddressEndpointLocationKey(key.getAddress(), key.getAddressType(), key.getContextId(),
+                key.getContextType());
+    }
+
     private static ProviderAddressEndpointLocationKey createProviderAddressEndpointLocationKey(ParentEndpointKey key) {
         return new ProviderAddressEndpointLocationKey(key.getAddress(), key.getAddressType(), key.getContextId(),
                 key.getContextType());
@@ -314,6 +360,10 @@ public class VppEndpointLocationProvider extends DataTreeChangeHandler<AddressEn
         return new VppEndpointKey(key.getAddress(), key.getAddressType(), key.getContextId(), key.getContextType());
     }
 
+    private VppEndpointKey vppEndpointKeyFrom(ChildEndpointKey key) {
+        return new VppEndpointKey(key.getAddress(), key.getAddressType(), key.getContextId(), key.getContextType());
+    }
+
     @Override
     public void close() {
         super.closeRegisteredListener();
@@ -326,12 +376,12 @@ public class VppEndpointLocationProvider extends DataTreeChangeHandler<AddressEn
 
         private final AddressEndpoint before;
         private final AddressEndpoint after;
-        private final DataBroker dataBroker;
+        private final BindingTransactionChain transactionChain;
 
-        public AddressEndpointChange(DataObjectModification<AddressEndpoint> addrEp, @Nonnull DataBroker dataBroker) {
+        public AddressEndpointChange(DataObjectModification<AddressEndpoint> addrEp, @Nonnull BindingTransactionChain txChain) {
             this.before = addrEp.getDataBefore();
             this.after = addrEp.getDataAfter();
-            this.dataBroker = dataBroker;
+            this.transactionChain = txChain;
         }
 
         boolean hasMoreParents() {
@@ -340,7 +390,7 @@ public class VppEndpointLocationProvider extends DataTreeChangeHandler<AddressEn
         }
 
         ListenableFuture<Void> syncMultiparents() {
-            ReadWriteTransaction rwTx = dataBroker.newReadWriteTransaction();
+            ReadWriteTransaction rwTx = transactionChain.newReadWriteTransaction();
             if (before != null) {
                 for (ParentEndpoint pe : EndpointUtils.getParentEndpoints(before.getParentEndpointChoice())) {
                     InstanceIdentifier<ProviderAddressEndpointLocation> iid =
@@ -355,17 +405,56 @@ public class VppEndpointLocationProvider extends DataTreeChangeHandler<AddressEn
                     InstanceIdentifier<ProviderAddressEndpointLocation> iid =
                             IidFactory.providerAddressEndpointLocationIid(VPP_ENDPOINT_LOCATION_PROVIDER,
                                     createProviderAddressEndpointLocationKey(pe.getKey()));
-                    ProviderAddressEndpointLocation location = createAbsoluteLocationFromVppEndpoint(
-                            new VppEndpointBuilder(vppEndpoint).setKey(vppEndpointKeyFrom(pe.getKey())).build());
-                    rwTx.put(LogicalDatastoreType.CONFIGURATION, iid, location, true);
+
+                    List<ChildEndpoint> childs = abc(rwTx, pe);
+                        List<VppEndpoint> vppEps = new ArrayList<>();
+                        for (ChildEndpoint che : childs) {
+                            VppEndpoint cheVppEp = vppEndpoints.get(vppEndpointKeyFrom(che.getKey()));
+                            if (cheVppEp != null) {
+                                vppEps.add(cheVppEp);
+                            } else {
+                            }
+                        }
+                        if (vppEps.size() > 1) {
+                        ProviderAddressEndpointLocation location = createRelativeLocationFromVppEndpoint(
+                                createProviderAddressEndpointLocationKey(pe.getKey()), vppEps);
+                        rwTx.put(LogicalDatastoreType.CONFIGURATION, iid, location, true);
+                    } else {
+                        ProviderAddressEndpointLocation location = createAbsoluteLocationFromVppEndpoint(
+                                new VppEndpointBuilder(vppEndpoint).setKey(vppEndpointKeyFrom(pe.getKey())).build());
+                        rwTx.put(LogicalDatastoreType.CONFIGURATION, iid, location, true);
+                    }
+
                 }
             }
             return rwTx.submit();
         }
 
+        private List<ChildEndpoint> abc(ReadWriteTransaction rTx, ParentEndpoint pe) {
+            AddressEndpointKey addrEpKey = new AddressEndpointKey(AddressEndpointUtils.fromParentEndpointKey(pe.getKey()));
+            Optional<AddressEndpoint> optParent = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL, IidFactory.addressEndpointIid(addrEpKey), rTx);
+            return (optParent.isPresent()) ? optParent.get().getChildEndpoint() : Collections.emptyList();
+        }
+
+        private ProviderAddressEndpointLocation createRelativeLocationFromVppEndpoint(
+                ProviderAddressEndpointLocationKey key, List<VppEndpoint> vppEndpoints) {
+            List<ExternalLocation> extLocations = vppEndpoints.stream().map(vppEndpoint -> {
+                InstanceIdentifier<Node> vppNodeIid = VppIidFactory.getNetconfNodeIid(vppEndpoint.getVppNodeId());
+                String restIfacePath = VppPathMapper.interfaceToRestPath(vppEndpoint.getVppInterfaceName());
+                return new ExternalLocationBuilder().setExternalNodeMountPoint(vppNodeIid)
+                    .setExternalNodeConnector(restIfacePath)
+                    .build();
+            }).collect(Collectors.toList());
+            RelativeLocations relativeLocations =
+                    new RelativeLocationsBuilder().setExternalLocation(extLocations).build();
+            return new ProviderAddressEndpointLocationBuilder().setRelativeLocations(relativeLocations)
+                .setKey(key)
+                .build();
+        }
+
         ListenableFuture<Void> write() {
             VppEndpoint vpp = vppEndpoints.get(vppEndpointKeyFrom(after.getKey()));
-            WriteTransaction wTx = dataBroker.newWriteOnlyTransaction();
+            WriteTransaction wTx = transactionChain.newWriteOnlyTransaction();
             ProviderAddressEndpointLocation location =
                     createAbsoluteLocationFromVppEndpoint(vpp);
             InstanceIdentifier<ProviderAddressEndpointLocation> iid = IidFactory.providerAddressEndpointLocationIid(
@@ -375,7 +464,7 @@ public class VppEndpointLocationProvider extends DataTreeChangeHandler<AddressEn
         }
 
         ListenableFuture<Void> delete() {
-            ReadWriteTransaction rwTx = dataBroker.newReadWriteTransaction();
+            ReadWriteTransaction rwTx = transactionChain.newReadWriteTransaction();
             InstanceIdentifier<ProviderAddressEndpointLocation> iid = IidFactory.providerAddressEndpointLocationIid(
                     VPP_ENDPOINT_LOCATION_PROVIDER, createProviderAddressEndpointLocationKey(before.getKey()));
             DataStoreHelper.removeIfExists(LogicalDatastoreType.CONFIGURATION, iid, rwTx);
index be7f5d09c9360679255f93b6791c90e7b0e2ddda..20ca4589a0d6aeeec20d3a77364c5d3bdc8551fc 100644 (file)
@@ -195,7 +195,7 @@ public final class ForwardingManager {
     public void createForwardingForEndpoint(RendererEndpointKey rEpKey, PolicyContext policyCtx) {
         AddressEndpointWithLocation rEp = policyCtx.getAddrEpByKey().get(KeyFactory.addressEndpointKey(rEpKey));
         ExternalLocationCase rEpLoc = resolveAndValidateLocation(rEp);
-        if (Strings.isNullOrEmpty(rEpLoc.getExternalNodeConnector())) {
+        if (rEpLoc == null || Strings.isNullOrEmpty(rEpLoc.getExternalNodeConnector())) {
             // TODO add it to the status for renderer manager
             LOG.info("Renderer endpoint does not have external-node-connector therefore it is ignored {}", rEp);
             return;
@@ -247,7 +247,7 @@ public final class ForwardingManager {
     public void removeForwardingForEndpoint(RendererEndpointKey rEpKey, PolicyContext policyCtx) {
         AddressEndpointWithLocation rEp = policyCtx.getAddrEpByKey().get(KeyFactory.addressEndpointKey(rEpKey));
         ExternalLocationCase rEpLoc = resolveAndValidateLocation(rEp);
-        if (Strings.isNullOrEmpty(rEpLoc.getExternalNodeConnector())) {
+        if (rEpLoc == null || Strings.isNullOrEmpty(rEpLoc.getExternalNodeConnector())) {
             // nothing was created for endpoint therefore nothing is removed
             return;
         }
@@ -267,15 +267,19 @@ public final class ForwardingManager {
     }
 
     public static ExternalLocationCase resolveAndValidateLocation(AddressEndpointWithLocation addrEpWithLoc) {
-        LocationType locationType = addrEpWithLoc.getAbsoluteLocation().getLocationType();
-        if (!(locationType instanceof ExternalLocationCase)) {
-            throw new IllegalStateException("Endpoint does not have external location " + addrEpWithLoc);
-        }
-        ExternalLocationCase result = (ExternalLocationCase) locationType;
-        if (result.getExternalNodeMountPoint() == null) {
-            throw new IllegalStateException("Endpoint does not have external-node-mount-point " + addrEpWithLoc);
+        if (addrEpWithLoc.getAbsoluteLocation() != null
+                && addrEpWithLoc.getAbsoluteLocation().getLocationType() != null) {
+            LocationType locationType = addrEpWithLoc.getAbsoluteLocation().getLocationType();
+            if (!(locationType instanceof ExternalLocationCase)) {
+                throw new IllegalStateException("Endpoint does not have external location " + addrEpWithLoc);
+            }
+            ExternalLocationCase result = (ExternalLocationCase) locationType;
+            if (result.getExternalNodeMountPoint() == null) {
+                throw new IllegalStateException("Endpoint does not have external-node-mount-point " + addrEpWithLoc);
+            }
+            return result;
         }
-        return result;
+        return null;
     }
 
     public static java.util.Optional<String> resolveL2FloodDomain(@Nonnull AddressEndpointWithLocation ep,
index b8bf8acca1f4fcdce38472fbb24c7c6f353251ee..eae4973da1d7a0c0fc7e471c3b8e7885d927457f 100644 (file)
@@ -88,7 +88,11 @@ public class PolicyContext {
                 new Builder<>();
         Supplier<TreeSet<RendererResolvedPolicy>> rendererPolicySupplier = () -> new TreeSet<>();
         rendererEps.stream().forEach(rEp -> {
-            rEp.getPeerEndpoint().stream().filter(Objects::nonNull).forEach(peer -> {
+            rEp.getPeerEndpoint()
+                .stream()
+                .filter(Objects::nonNull)
+                .filter(peer -> peer.getRuleGroupWithRendererEndpointParticipation() != null)
+                .forEach(peer -> {
                 ImmutableSortedSet<RendererResolvedPolicy> rPolicy =
                         peer.getRuleGroupWithRendererEndpointParticipation()
                             .stream()
index 59d80322d67c2a32cd3e0810b7d3a0b4dc6c50e5..795fefc6a3b05d3ecad0dcd9479382addc0bafb5 100644 (file)
@@ -234,10 +234,11 @@ public class VppRendererPolicyManager {
                                     new RuleGroupKey(rg.getContractId(), rg.getSubjectName(), rg.getTenantId()))) {
                                 continue;
                             }
-                            LOG.debug("Updated resolved rule group: {}. Affected endpoints {} and {}.", rg.getKey(), rEp.getKey(), pEp.getKey());
-                            updates.add(rEp.getKey());
-                            AddressEndpointKey k1 = AddressEndpointUtils.fromPeerEpKey(pEp.getKey());
-                            updates.add(AddressEndpointUtils.toRendererEpKey(k1));
+                            if (!policy.equals(policyCtxBefore)) {
+                                updates.add(rEp.getKey());
+                                AddressEndpointKey k1 = AddressEndpointUtils.fromPeerEpKey(pEp.getKey());
+                                updates.add(AddressEndpointUtils.toRendererEpKey(k1));
+                            }
                         }
                     }
                 });
@@ -250,6 +251,12 @@ public class VppRendererPolicyManager {
     private static boolean isLocationChanged(AddressEndpointWithLocation before, AddressEndpointWithLocation after) {
         ExternalLocationCase locationBefore = ForwardingManager.resolveAndValidateLocation(before);
         ExternalLocationCase locationAfter = ForwardingManager.resolveAndValidateLocation(after);
+        if(locationBefore == null && locationAfter == null) {
+            return false;
+        }
+        if(locationBefore == null || locationAfter == null) {
+            return true;
+        }
         return !locationBefore.equals(locationAfter);
     }
 
@@ -300,9 +307,11 @@ public class VppRendererPolicyManager {
                 java.util.Optional<String> optL2Fd = ForwardingManager.resolveL2FloodDomain(addrEpWithLoc, policyCtx);
                 if (optL2Fd.isPresent()) {
                     ExternalLocationCase rEpLoc = ForwardingManager.resolveAndValidateLocation(addrEpWithLoc);
-                    InstanceIdentifier<?> externalNodeMountPoint = rEpLoc.getExternalNodeMountPoint();
-                    NodeId vppNode = externalNodeMountPoint.firstKeyOf(Node.class).getNodeId();
-                    vppNodesByL2Fd.put(optL2Fd.get(), vppNode);
+                    if (rEpLoc != null) {
+                        InstanceIdentifier<?> externalNodeMountPoint = rEpLoc.getExternalNodeMountPoint();
+                        NodeId vppNode = externalNodeMountPoint.firstKeyOf(Node.class).getNodeId();
+                        vppNodesByL2Fd.put(optL2Fd.get(), vppNode);
+                    }
                 }
             });
         return vppNodesByL2Fd;
index aba8d120066877c13536bc7730caa1f33ed429ef..17432e7cf9755dae4a19415f38b410d7f7e2a99f 100644 (file)
@@ -10,6 +10,8 @@ package org.opendaylight.groupbasedpolicy.renderer.vpp.policy.acl;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Set;
+import java.util.function.Predicate;
 import java.util.stream.Collectors;
 
 import javax.annotation.Nonnull;
@@ -141,24 +143,40 @@ public class AclManager {
         multipleEndpointsOnInterface = resultBuilder.build();
     }
 
-    private void resolveEndpointsOnMultipleInterface(@Nullable ImmutableList<AddressEndpointWithLocation> eps,
+    /**
+     *  Recursively grouping interfaces behind the same port
+     */
+    private void resolveEndpointsOnMultipleInterface(@Nullable List<AddressEndpointWithLocation> eps,
             @Nonnull Builder<NodeId, InterfaceKey, ImmutableSet<AddressEndpointKey>> builder) {
         if (eps == null || eps.isEmpty()) {
             return;
         }
-        eps.get(0);
-        ImmutableSet<AddressEndpointKey> copyOf = ImmutableSet.copyOf(eps.stream()
-            .filter(addrEp -> AddressEndpointUtils.sameExternalLocationCase(eps.get(0), addrEp))
+        // look for any end-point with absolute location as reference end-point in this cycle;
+        java.util.Optional<AddressEndpointWithLocation> refEndpoint =
+                eps.stream().filter(ep -> EndpointUtils.getExternalLocationFrom(ep).isPresent()).findAny();
+        if (!refEndpoint.isPresent()) {
+            return;
+        }
+        Predicate<AddressEndpointWithLocation> sameLocation = new Predicate<AddressEndpointWithLocation>() {
+            @Override
+            public boolean test(AddressEndpointWithLocation addrEp) {
+                return AddressEndpointUtils.sameExternalLocationCase(refEndpoint.get(), addrEp);
+            }
+        };
+        Optional<ExternalLocationCase> extLoc = EndpointUtils.getExternalLocationFrom(refEndpoint.get());
+        Set<AddressEndpointKey> sameLocations = eps.stream()
+            .filter(sameLocation)
             .map(addrEp -> AddressEndpointUtils.fromAddressEndpointWithLocationKey(addrEp.getKey()))
-            .collect(Collectors.toSet()));
-        Optional<ExternalLocationCase> extLoc = EndpointUtils.getExternalLocationFrom(eps.get(0));
+            .collect(Collectors.toSet());
         builder.put(extLoc.get().getExternalNodeMountPoint().firstKeyOf(Node.class).getNodeId(),
-                new InterfaceKey(extLoc.get().getExternalNodeConnector()), copyOf);
-        ImmutableList<AddressEndpointWithLocation> lisst = ImmutableList.copyOf(eps.stream()
-            .filter(addrEp -> !AddressEndpointUtils.sameExternalLocationCase(eps.get(0), addrEp))
-            .collect(Collectors.toList()));
-        if (!lisst.isEmpty()) {
-            resolveEndpointsOnMultipleInterface(lisst, builder);
+                new InterfaceKey(extLoc.get().getExternalNodeConnector()),
+                ImmutableSet.<AddressEndpointKey>copyOf(sameLocations));
+        List<AddressEndpointWithLocation> differentLocations = eps.stream()
+            //  keep end-points with different location and end-points with relative location in loop
+            .filter(sameLocation.negate().or(p -> !EndpointUtils.getExternalLocationFrom(p).isPresent()))
+            .collect(Collectors.toList());
+        if (!differentLocations.isEmpty()) {
+            resolveEndpointsOnMultipleInterface(differentLocations, builder);
         }
     }
 
index 6a766cba573c2e581f6315432275c416fb1ed150..0db3e601bb7738cc42b90c930ce6bf704ab37874 100644 (file)
@@ -25,14 +25,11 @@ import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.location.type.ExternalLocationCase;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.location.type.ExternalLocationCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContextId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint_location_provider.rev160419.location.providers.LocationProvider;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint_location_provider.rev160419.location.providers.location.provider.ProviderAddressEndpointLocation;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.IpPrefixType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.L3Context;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocationKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.VppEndpoint;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.VppEndpointBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.VppEndpointKey;
@@ -112,21 +109,6 @@ public class VppEndpointLocationProviderTest {
         verify(rwTx, times(1)).submit();
     }
 
-    @Test
-    public void replaceLocationForEndpointTest() {
-        final VppEndpointLocationProvider locationProvider = new VppEndpointLocationProvider(dataProvider);
-        final ListenableFuture<Void> result =
-                locationProvider.replaceLocationForEndpoint(externalLocationCaseBuilder(), getAddressEpKey());
-        Assert.assertNotNull(result);
-        verify(dataProvider, times(1)).createTransactionChain(any());
-        verify(transactionChain, times(2)).newWriteOnlyTransaction();
-        verify(wTx, times(1)).put(eq(LogicalDatastoreType.CONFIGURATION),
-                any(InstanceIdentifier.class), any(LocationProvider.class), eq(true));
-        verify(wTx, times(1)).put(eq(LogicalDatastoreType.CONFIGURATION),
-                any(InstanceIdentifier.class), any(ProviderAddressEndpointLocation.class));
-        verify(wTx, times(2)).submit();
-    }
-
 
     private VppEndpoint vppEndpointBuilder() {
         final VppEndpointBuilder vppEndpointBuilder = new VppEndpointBuilder();
@@ -134,14 +116,4 @@ public class VppEndpointLocationProviderTest {
         return vppEndpointBuilder.build();
     }
 
-    private ExternalLocationCase externalLocationCaseBuilder() {
-        final ExternalLocationCaseBuilder externalLocationCaseBuilder = new ExternalLocationCaseBuilder();
-        return externalLocationCaseBuilder.build();
-    }
-
-    private AddressEndpointWithLocationKey getAddressEpKey() {
-        final String ADDRESS_EP_KEY = "address-ep-key";
-        return new AddressEndpointWithLocationKey(ADDRESS_EP_KEY, IpPrefixType.class, contextId, L3Context.class);
-    }
-
 }
\ No newline at end of file
index 112c8aadbea1263a60da294f084463e977bcc426..1385f250f9301c3e5d9d9aa30621ffe7d13de094 100644 (file)
@@ -11,6 +11,7 @@ package org.opendaylight.groupbasedpolicy.renderer.vpp.policy;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.List;
+import java.util.concurrent.ExecutionException;
 import java.util.stream.Collectors;
 
 import org.junit.Assert;
@@ -22,6 +23,7 @@ import org.mockito.runners.MockitoJUnitRunner;
 import org.opendaylight.controller.config.yang.config.vpp_provider.impl.VppRenderer;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.DtoFactory;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.event.RendererPolicyConfEvent;
@@ -35,9 +37,15 @@ import org.opendaylight.groupbasedpolicy.renderer.vpp.util.KeyFactory;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.MountedDataBrokerProvider;
 import org.opendaylight.groupbasedpolicy.test.CustomDataBrokerTest;
 import org.opendaylight.groupbasedpolicy.util.IidFactory;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.AccessLists;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.Endpoints;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.AddressEndpoints;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpoint;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpointBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpointKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.AbsoluteLocation;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint_location_provider.rev160419.LocationProviders;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint_location_provider.rev160419.location.providers.LocationProvider;
@@ -60,9 +68,12 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315.interfaces._interface.L2;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315.l2.base.attributes.Interconnection;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315.l2.base.attributes.interconnection.BridgeBased;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.acl.rev161214.VppAclInterfaceAugmentation;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315.BridgeDomains;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vbridge.topology.rev160129.TopologyVbridgeAugment;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vbridge.tunnel.vxlan.rev160429.TunnelTypeVxlan;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vbridge.tunnel.vxlan.rev170327.network.topology.topology.tunnel.parameters.VxlanTunnelParameters;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.access.lists.acl.access.list.entries.ace.matches.ace.type.VppAce;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
@@ -90,9 +101,11 @@ public class VppRendererPolicyManagerTest extends CustomDataBrokerTest {
 
     @Override
     public Collection<Class<?>> getClassesFromModules() {
+        //org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.access.lists.acl.access.list.entries.ace.matches
         return Arrays.asList(Node.class, VppEndpoint.class, Interfaces.class, BridgeDomains.class,
                 LocationProviders.class, L2FloodDomain.class, VxlanVni.class, TopologyVbridgeAugment.class,
-                TunnelTypeVxlan.class, PhysicalLocationRef.class);
+                TunnelTypeVxlan.class, PhysicalLocationRef.class, AccessLists.class, VppAce.class,
+                VppInterfaceAugmentation.class, VppAclInterfaceAugmentation.class, VxlanTunnelParameters.class);
     }
 
     @Before
@@ -147,6 +160,7 @@ public class VppRendererPolicyManagerTest extends CustomDataBrokerTest {
                 IidFactory.locationProviderIid(VppEndpointLocationProvider.VPP_ENDPOINT_LOCATION_PROVIDER))
             .get();
         Assert.assertTrue(optLocationProvider.isPresent());
+        System.out.println("DEBUGG " + optLocationProvider.get());
         List<ProviderAddressEndpointLocation> epLocs = optLocationProvider.get().getProviderAddressEndpointLocation();
         Assert.assertNotNull(epLocs);
         Assert.assertEquals(2, epLocs.size());
@@ -365,12 +379,26 @@ public class VppRendererPolicyManagerTest extends CustomDataBrokerTest {
         }
     }
 
-    private void storeVppEndpoint(AddressEndpointWithLocationKey epKey, String ifaceName,
+    private void storeVppEndpoint(AddressEndpointWithLocationKey clientEp, String ifaceName,
             InstanceIdentifier<VppEndpoint> vppEpIid) {
-        VppEndpoint vhostEp = new VppEndpointBuilder().setAddress(epKey.getAddress())
-            .setAddressType(epKey.getAddressType())
-            .setContextId(epKey.getContextId())
-            .setContextType(epKey.getContextType())
+        AddressEndpoint addrEp = new AddressEndpointBuilder().setKey(new AddressEndpointKey(clientEp.getAddress(),
+                clientEp.getAddressType(), clientEp.getContextId(), clientEp.getContextType()))
+            .build();
+        InstanceIdentifier<AddressEndpoint> iid = InstanceIdentifier.create(Endpoints.class)
+            .child(AddressEndpoints.class)
+            .child(AddressEndpoint.class, addrEp.getKey());
+        WriteTransaction wTx = dataBroker.newWriteOnlyTransaction();
+        wTx.put(LogicalDatastoreType.OPERATIONAL, iid, addrEp);
+        try {
+            wTx.submit().get();
+        } catch (InterruptedException | ExecutionException e) {
+            e.printStackTrace();
+        }
+
+        VppEndpoint vhostEp = new VppEndpointBuilder().setAddress(clientEp.getAddress())
+            .setAddressType(clientEp.getAddressType())
+            .setContextId(clientEp.getContextId())
+            .setContextType(clientEp.getContextType())
             .setVppInterfaceName(ifaceName)
             .setVppNodeId(DtoFactory.VPP_NODE_1_IID.firstKeyOf(Node.class).getNodeId())
             .setInterfaceTypeChoice(new VhostUserCaseBuilder().setSocket(SOCKET).build())