Security group in VPP renderer
[groupbasedpolicy.git] / groupbasedpolicy / src / main / java / org / opendaylight / groupbasedpolicy / renderer / RendererManager.java
index becf45e459f0e674c624a7e17fb039bfecf97732..baaf223797c8ec2a5e33bad912cb1f49f6b2fa48 100644 (file)
@@ -10,6 +10,8 @@ package org.opendaylight.groupbasedpolicy.renderer;
 
 import static com.google.common.base.Preconditions.checkNotNull;
 
+import javax.annotation.Nullable;
+
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -18,19 +20,30 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
-import javax.annotation.Nullable;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableCollection;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableMultimap;
+import com.google.common.collect.ImmutableSet;
 
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.groupbasedpolicy.base_endpoint.EndpointAugmentorRegistryImpl;
 import org.opendaylight.groupbasedpolicy.dto.ConsEpgKey;
 import org.opendaylight.groupbasedpolicy.dto.EpgKeyDto;
 import org.opendaylight.groupbasedpolicy.dto.ProvEpgKey;
+import org.opendaylight.groupbasedpolicy.forwarding.NetworkDomainAugmentorRegistryImpl;
 import org.opendaylight.groupbasedpolicy.renderer.listener.EndpointLocationsListener;
 import org.opendaylight.groupbasedpolicy.renderer.listener.EndpointsListener;
 import org.opendaylight.groupbasedpolicy.renderer.listener.ForwardingListener;
 import org.opendaylight.groupbasedpolicy.renderer.listener.RenderersListener;
 import org.opendaylight.groupbasedpolicy.renderer.listener.ResolvedPoliciesListener;
+import org.opendaylight.groupbasedpolicy.renderer.util.AddressEndpointUtils;
+import org.opendaylight.groupbasedpolicy.renderer.util.ContainmentEndpointUtils;
 import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.EndpointLocations;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.Endpoints;
@@ -44,9 +57,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.RendererName;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.Renderers;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.RenderersBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.has.peer.endpoints.PeerEndpointKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.has.peer.external.containment.endpoints.PeerExternalContainmentEndpointKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.has.peer.external.endpoints.PeerExternalEndpointKey;
 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.RendererBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.RendererPolicy;
@@ -54,10 +64,13 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.Configuration;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.ConfigurationBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.Status;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.ForwardingContexts;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.RendererEndpoints;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.RendererForwarding;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.RuleGroups;
 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.PeerExternalContainmentEndpointKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.renderer.endpoint.PeerExternalEndpointKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.ResolvedPolicies;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.ResolvedPolicy;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.ResolvedPolicy.ExternalImplicitGroup;
@@ -67,15 +80,6 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 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.collect.FluentIterable;
-import com.google.common.collect.ImmutableCollection;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableMultimap;
-import com.google.common.collect.ImmutableSet;
-
 public class RendererManager implements AutoCloseable {
 
     private static final Logger LOG = LoggerFactory.getLogger(RendererManager.class);
@@ -83,12 +87,12 @@ public class RendererManager implements AutoCloseable {
     private static long version = 0;
 
     private final DataBroker dataProvider;
+    private final NetworkDomainAugmentorRegistryImpl netDomainAugmentorRegistry;
+    private final EndpointAugmentorRegistryImpl epAugmentorRegistry;
     private final Set<RendererName> processingRenderers = new HashSet<>();
-    private Map<InstanceIdentifier<?>, RendererName> rendererByNode = new HashMap<>();
-    private ResolvedPolicyInfo policyInfo;
-    private EndpointInfo epInfo;
-    private EndpointLocationInfo epLocInfo;
-    private Forwarding forwarding;
+    private InputState currentState = new InputState();
+    private InputState configuredState;
+    private boolean currentVersionHasConfig = false;
 
     private final EndpointsListener endpointsListener;
     private final EndpointLocationsListener endpointLocationsListener;
@@ -96,8 +100,95 @@ public class RendererManager implements AutoCloseable {
     private final ForwardingListener forwardingListener;
     private final RenderersListener renderersListener;
 
-    public RendererManager(DataBroker dataProvider) {
+    private static final class InputState {
+
+        private ResolvedPolicyInfo policyInfo;
+        private EndpointInfo epInfo;
+        private EndpointLocationInfo epLocInfo;
+        private Forwarding forwarding;
+        private Map<InstanceIdentifier<?>, RendererName> rendererByNode = new HashMap<>();
+
+        private boolean isValid() {
+            if (rendererByNode.isEmpty() || policyInfo == null || epInfo == null || epLocInfo == null
+                    || forwarding == null) {
+                return false;
+            }
+            return true;
+        }
+
+        private InputState createCopy() {
+            InputState copy = new InputState();
+            copy.policyInfo = this.policyInfo;
+            copy.epInfo = this.epInfo;
+            copy.epLocInfo = this.epLocInfo;
+            copy.forwarding = this.forwarding;
+            copy.rendererByNode = ImmutableMap.copyOf(rendererByNode);
+            return copy;
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + ((epInfo == null) ? 0 : epInfo.hashCode());
+            result = prime * result + ((epLocInfo == null) ? 0 : epLocInfo.hashCode());
+            result = prime * result + ((forwarding == null) ? 0 : forwarding.hashCode());
+            result = prime * result + ((policyInfo == null) ? 0 : policyInfo.hashCode());
+            result = prime * result + ((rendererByNode == null) ? 0 : rendererByNode.hashCode());
+            return result;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj)
+                return true;
+            if (obj == null)
+                return false;
+            if (getClass() != obj.getClass())
+                return false;
+            InputState other = (InputState) obj;
+            if (epInfo == null) {
+                if (other.epInfo != null)
+                    return false;
+            } else if (!epInfo.equals(other.epInfo))
+                return false;
+            if (epLocInfo == null) {
+                if (other.epLocInfo != null)
+                    return false;
+            } else if (!epLocInfo.equals(other.epLocInfo))
+                return false;
+            if (forwarding == null) {
+                if (other.forwarding != null)
+                    return false;
+            } else if (!DtoEquivalenceUtils.equalsForwarding(forwarding, other.forwarding))
+                return false;
+            if (policyInfo == null) {
+                if (other.policyInfo != null)
+                    return false;
+            } else if (!policyInfo.equals(other.policyInfo))
+                return false;
+            if (rendererByNode == null) {
+                if (other.rendererByNode != null)
+                    return false;
+            } else if (!rendererByNode.equals(other.rendererByNode))
+                return false;
+            return true;
+        }
+
+        @Override
+        public String toString() {
+            return "InputState [policyInfo=" + policyInfo + ", epInfo=" + epInfo + ", epLocInfo=" + epLocInfo
+                    + ", forwarding=" + forwarding + ", rendererByNode=" + rendererByNode + ", isValid()=" + isValid()
+                    + "]";
+        }
+
+    }
+
+    public RendererManager(DataBroker dataProvider, NetworkDomainAugmentorRegistryImpl netDomainAugmentorRegistry,
+                           EndpointAugmentorRegistryImpl epAugmentorRegistry) {
         this.dataProvider = checkNotNull(dataProvider);
+        this.netDomainAugmentorRegistry = checkNotNull(netDomainAugmentorRegistry);
+        this.epAugmentorRegistry = checkNotNull(epAugmentorRegistry);
         endpointsListener = new EndpointsListener(this, dataProvider);
         endpointLocationsListener = new EndpointLocationsListener(this, dataProvider);
         resolvedPoliciesListener = new ResolvedPoliciesListener(this, dataProvider);
@@ -106,37 +197,35 @@ public class RendererManager implements AutoCloseable {
     }
 
     public synchronized void endpointsUpdated(final Endpoints endpoints) {
-        epInfo = new EndpointInfo(endpoints);
+        currentState.epInfo = new EndpointInfo(endpoints);
         processState();
     }
 
     public synchronized void endpointLocationsUpdated(final EndpointLocations epLocations) {
-        epLocInfo = new EndpointLocationInfo(epLocations);
+        currentState.epLocInfo = new EndpointLocationInfo(epLocations);
         processState();
     }
 
     public synchronized void resolvedPoliciesUpdated(final ResolvedPolicies resolvedPolicies) {
-        policyInfo = new ResolvedPolicyInfo(resolvedPolicies);
+        currentState.policyInfo = new ResolvedPolicyInfo(resolvedPolicies);
         processState();
     }
 
     public synchronized void forwardingUpdated(final Forwarding forwarding) {
-        this.forwarding = forwarding;
+        currentState.forwarding = forwarding;
         processState();
     }
 
     public synchronized void renderersUpdated(final Renderers renderersCont) {
         ImmutableMultimap<InstanceIdentifier<?>, RendererName> renderersByNode =
                 RendererUtils.resolveRenderersByNodes(renderersCont.getRenderer());
-        rendererByNode = new HashMap<>();
+        currentState.rendererByNode = new HashMap<>();
         for (InstanceIdentifier<?> nodePath : renderersByNode.keySet()) {
             ImmutableCollection<RendererName> renderers = renderersByNode.get(nodePath);
             // only first renderer is used
-            rendererByNode.put(nodePath, renderers.asList().get(0));
+            currentState.rendererByNode.put(nodePath, renderers.asList().get(0));
         }
-        if (processingRenderers.isEmpty()) {
-            processState();
-        } else {
+        if (!processingRenderers.isEmpty()) {
             LOG.debug("Waiting for renderers. Version {} needs to be processed by renderers: {}", version,
                     processingRenderers);
             ImmutableMap<RendererName, Renderer> rendererByName =
@@ -148,7 +237,9 @@ public class RendererManager implements AutoCloseable {
                         && renderer.getRendererPolicy().getVersion().equals(version)) {
                     processingRenderers.remove(configuredRenderer);
                     Status status = rendererPolicy.getStatus();
-                    if (status != null && status.getUnconfiguredRule() != null) {
+                    if (status != null && status.getUnconfiguredEndpoints() != null
+                            && status.getUnconfiguredEndpoints().getUnconfiguredRendererEndpoint() != null
+                            && !status.getUnconfiguredEndpoints().getUnconfiguredRendererEndpoint().isEmpty()) {
                         LOG.warn("Renderer {} did not configure policy with version {} successfully. \n{}",
                                 configuredRenderer.getValue(), version, status);
                     } else {
@@ -158,6 +249,7 @@ public class RendererManager implements AutoCloseable {
                 }
             }
         }
+        processState();
     }
 
     private void processState() {
@@ -166,56 +258,76 @@ public class RendererManager implements AutoCloseable {
                     processingRenderers);
             return;
         }
-        if (rendererByNode.values().isEmpty()) {
+        if (currentState.equals(configuredState)) {
+            LOG.trace("Nothing was changed in config for renderers {}", currentState);
             return;
         }
-
-        version++;
-        Map<RendererName, RendererConfigurationBuilder> rendererConfigBuilderByRendererName = createRendererConfigBuilders();
-        List<Renderer> renderers = new ArrayList<>();
-        Set<RendererName> rendererNames = new HashSet<>(rendererByNode.values());
+        Map<RendererName, RendererConfigurationBuilder> rendererConfigBuilderByRendererName =
+                createRendererConfigBuilders();
+        Set<RendererName> rendererNames = new HashSet<>(currentState.rendererByNode.values());
+        boolean newVersionHasConfig = false;
+        Map<RendererName, Optional<Configuration>> configsByRendererName = new HashMap<>();
         for (RendererName rendererName : rendererNames) {
             RendererConfigurationBuilder rendererPolicyBuilder = rendererConfigBuilderByRendererName.get(rendererName);
             Optional<Configuration> potentialConfig = createConfiguration(rendererPolicyBuilder);
-            RendererPolicy rendererPolicy = null;
             if (potentialConfig.isPresent()) {
-                LOG.debug("Created configuration for renderer with version {}", rendererName.getValue(), version);
-                rendererPolicy =
-                        new RendererPolicyBuilder().setVersion(version).setConfiguration(potentialConfig.get()).build();
+                newVersionHasConfig = true;
+            }
+            configsByRendererName.put(rendererName, potentialConfig);
+        }
+        if (newVersionHasConfig || currentVersionHasConfig) {
+            version++;
+            if (!writeRenderersConfigs(configsByRendererName)) {
+                LOG.warn("Version {} was not dispatched successfully. Previous version is valid until next update.",
+                        version);
+                for (RendererName rendererName : rendererConfigBuilderByRendererName.keySet()) {
+                    processingRenderers.remove(rendererName);
+                }
+                version--;
+                return;
+            } else {
+                currentVersionHasConfig = newVersionHasConfig;
+                configuredState = currentState.createCopy();
+            }
+        }
+    }
+
+    private boolean writeRenderersConfigs(Map<RendererName, Optional<Configuration>> configsByRendererName) {
+        List<Renderer> renderers = new ArrayList<>();
+        for (RendererName rendererName : configsByRendererName.keySet()) {
+            RendererPolicy rendererPolicy;
+            if (configsByRendererName.get(rendererName).isPresent()) {
+                rendererPolicy = new RendererPolicyBuilder().setVersion(version)
+                        .setConfiguration(configsByRendererName.get(rendererName).get())
+                        .build();
+
             } else {
-                rendererPolicy =
-                        new RendererPolicyBuilder().setVersion(version).build();
+                rendererPolicy = new RendererPolicyBuilder().setVersion(version).build();
             }
             renderers.add(new RendererBuilder().setName(rendererName).setRendererPolicy(rendererPolicy).build());
             processingRenderers.add(rendererName);
+            LOG.debug("Created configuration for renderer {} with version {}", rendererName.getValue(), version);
         }
         WriteTransaction wTx = dataProvider.newWriteOnlyTransaction();
         wTx.put(LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.create(Renderers.class),
                 new RenderersBuilder().setRenderer(renderers).build());
-        if (!DataStoreHelper.submitToDs(wTx)) {
-            LOG.warn("Version {} was not dispatched successfully. Previous version is valid till next update.",
-                    version);
-            for (RendererName rendererName : rendererConfigBuilderByRendererName.keySet()) {
-                processingRenderers.remove(rendererName);
-            }
-            version--;
-        }
+        return DataStoreHelper.submitToDs(wTx);
     }
 
     /**
      * Entry is added to the result map only if:<br>
      * 1. There is at least one Address EP with absolute location
      * 2. There is a renderer responsible for that EP
-     * 
+     *
      * @return
      */
     private Map<RendererName, RendererConfigurationBuilder> createRendererConfigBuilders() {
-        if (!isStateValid()) {
+        if (!currentState.isValid()) {
             return Collections.emptyMap();
         }
         Map<RendererName, RendererConfigurationBuilder> rendererConfigBuilderByRendererName = new HashMap<>();
-        for (InstanceIdentifier<?> absEpLocation : epLocInfo.getAllAbsoluteNodeLocations()) {
-            RendererName rendererName = rendererByNode.get(absEpLocation);
+        for (InstanceIdentifier<?> absEpLocation : currentState.epLocInfo.getAllAbsoluteNodeLocations()) {
+            RendererName rendererName = currentState.rendererByNode.get(absEpLocation);
             if (rendererName == null) {
                 LOG.trace("Renderer does not exist for EP with location: {}", absEpLocation);
                 continue;
@@ -225,8 +337,9 @@ public class RendererManager implements AutoCloseable {
                 rendererConfigBuilder = new RendererConfigurationBuilder();
                 rendererConfigBuilderByRendererName.put(rendererName, rendererConfigBuilder);
             }
-            for (AddressEndpointKey rendererAdrEpKey : epLocInfo.getAddressEpsWithAbsoluteNodeLocation(absEpLocation)) {
-                Optional<AddressEndpoint> potentialAddressEp = epInfo.getEndpoint(rendererAdrEpKey);
+            for (AddressEndpointKey rendererAdrEpKey : currentState.epLocInfo
+                    .getAddressEpsWithAbsoluteNodeLocation(absEpLocation)) {
+                Optional<AddressEndpoint> potentialAddressEp = currentState.epInfo.getEndpoint(rendererAdrEpKey);
                 if (!potentialAddressEp.isPresent()) {
                     LOG.trace("Endpoint does not exist but has location: {}", rendererAdrEpKey);
                     continue;
@@ -238,14 +351,6 @@ public class RendererManager implements AutoCloseable {
         return rendererConfigBuilderByRendererName;
     }
 
-    private boolean isStateValid() {
-        if (rendererByNode.isEmpty() || policyInfo == null || epInfo == null || epLocInfo == null
-                || forwarding == null) {
-            return false;
-        }
-        return true;
-    }
-
     private Optional<Configuration> createConfiguration(@Nullable RendererConfigurationBuilder rendererPolicyBuilder) {
         if (rendererPolicyBuilder == null) {
             return Optional.absent();
@@ -258,14 +363,16 @@ public class RendererManager implements AutoCloseable {
         configBuilder.setRendererEndpoints(rendererEndpoints);
 
         org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.Endpoints endpoints =
-                rendererPolicyBuilder.buildEndoints(epInfo, epLocInfo, rendererByNode);
+                rendererPolicyBuilder.buildEndpoints(currentState.epInfo, currentState.epLocInfo,
+                        currentState.rendererByNode, epAugmentorRegistry.getEndpointAugmentors());
         configBuilder.setEndpoints(endpoints);
 
-        RuleGroups ruleGroups = rendererPolicyBuilder.buildRuluGroups(policyInfo);
+        RuleGroups ruleGroups = rendererPolicyBuilder.buildRuleGroups(currentState.policyInfo);
         configBuilder.setRuleGroups(ruleGroups);
 
-        ForwardingContexts forwardingContexts = rendererPolicyBuilder.buildForwardingContexts(forwarding);
-        configBuilder.setForwardingContexts(forwardingContexts);
+        RendererForwarding rendererForwarding = rendererPolicyBuilder.buildRendererForwarding(currentState.forwarding,
+                netDomainAugmentorRegistry.getNetworkDomainAugmentors());
+        configBuilder.setRendererForwarding(rendererForwarding);
 
         return Optional.of(configBuilder.build());
     }
@@ -280,29 +387,33 @@ public class RendererManager implements AutoCloseable {
 
     @VisibleForTesting
     void resolveRendererConfigForEndpoint(AddressEndpoint rendererAdrEp,
-            RendererConfigurationBuilder rendererPolicyBuilder) {
+                                          RendererConfigurationBuilder rendererPolicyBuilder) {
         Set<EpgKeyDto> rendererEpgs = toEpgKeys(rendererAdrEp.getEndpointGroup(), rendererAdrEp.getTenant());
         RendererEndpointKey rendererEpKey = AddressEndpointUtils.toRendererEpKey(rendererAdrEp.getKey());
         for (EpgKeyDto rendererEpg : rendererEpgs) {
-            ImmutableSet<ConsEpgKey> consPeerEpgs = policyInfo.findConsumerPeers(rendererEpg);
+            ImmutableSet<ConsEpgKey> consPeerEpgs = currentState.policyInfo.findConsumerPeers(rendererEpg);
             for (ConsEpgKey consPeerEpg : consPeerEpgs) {
-                Optional<ResolvedPolicy> potentialPolicy = policyInfo.findPolicy(consPeerEpg, rendererEpg);
+                Optional<ResolvedPolicy> potentialPolicy = currentState.policyInfo.findPolicy(consPeerEpg, rendererEpg);
                 ResolvedPolicy policy = potentialPolicy.get();
-                ImmutableSet<AddressEndpointKey> consPeerAdrEps = epInfo.findAddressEpsWithEpg(consPeerEpg);
+                ImmutableSet<AddressEndpointKey> consPeerAdrEps =
+                        currentState.epInfo.findAddressEpsWithEpg(consPeerEpg);
                 resolveRendererPolicyBetweenEpAndPeers(rendererEpKey, consPeerAdrEps, policy,
                         EndpointPolicyParticipation.PROVIDER, rendererPolicyBuilder);
-                ImmutableSet<ContainmentEndpointKey> consPeerContEps = epInfo.findContainmentEpsWithEpg(consPeerEpg);
+                ImmutableSet<ContainmentEndpointKey> consPeerContEps =
+                        currentState.epInfo.findContainmentEpsWithEpg(consPeerEpg);
                 resolveRendererPolicyBetweenEpAndContPeers(rendererEpKey, consPeerContEps, policy,
                         EndpointPolicyParticipation.PROVIDER, rendererPolicyBuilder);
             }
-            ImmutableSet<ProvEpgKey> provPeerEpgs = policyInfo.findProviderPeers(rendererEpg);
+            ImmutableSet<ProvEpgKey> provPeerEpgs = currentState.policyInfo.findProviderPeers(rendererEpg);
             for (ProvEpgKey provPeerEpg : provPeerEpgs) {
-                Optional<ResolvedPolicy> potentialPolicy = policyInfo.findPolicy(rendererEpg, provPeerEpg);
+                Optional<ResolvedPolicy> potentialPolicy = currentState.policyInfo.findPolicy(rendererEpg, provPeerEpg);
                 ResolvedPolicy policy = potentialPolicy.get();
-                ImmutableSet<AddressEndpointKey> provPeerAdrEps = epInfo.findAddressEpsWithEpg(provPeerEpg);
+                ImmutableSet<AddressEndpointKey> provPeerAdrEps =
+                        currentState.epInfo.findAddressEpsWithEpg(provPeerEpg);
                 resolveRendererPolicyBetweenEpAndPeers(rendererEpKey, provPeerAdrEps, policy,
                         EndpointPolicyParticipation.CONSUMER, rendererPolicyBuilder);
-                ImmutableSet<ContainmentEndpointKey> provPeerContEps = epInfo.findContainmentEpsWithEpg(provPeerEpg);
+                ImmutableSet<ContainmentEndpointKey> provPeerContEps =
+                        currentState.epInfo.findContainmentEpsWithEpg(provPeerEpg);
                 resolveRendererPolicyBetweenEpAndContPeers(rendererEpKey, provPeerContEps, policy,
                         EndpointPolicyParticipation.CONSUMER, rendererPolicyBuilder);
             }
@@ -310,8 +421,8 @@ public class RendererManager implements AutoCloseable {
     }
 
     private void resolveRendererPolicyBetweenEpAndContPeers(RendererEndpointKey rendererEpKey,
-            Set<ContainmentEndpointKey> peerContEps, ResolvedPolicy policy,
-            EndpointPolicyParticipation rendererEpParticipation, RendererConfigurationBuilder rendererPolicyBuilder) {
+                                                            Set<ContainmentEndpointKey> peerContEps, ResolvedPolicy policy,
+                                                            EndpointPolicyParticipation rendererEpParticipation, RendererConfigurationBuilder rendererPolicyBuilder) {
         if (isRendererEpInEig(policy, rendererEpParticipation)) {
             LOG.info("Renderer EP cannot be in EIG therefore it is ignored: {}. \nPolicy: {}", rendererEpKey);
             LOG.debug("Renderer EP participation: {}, Policy: {}", rendererEpParticipation, policy);
@@ -320,7 +431,7 @@ public class RendererManager implements AutoCloseable {
         for (ContainmentEndpointKey peerContEpKey : peerContEps) {
             ExternalImplicitGroup eig = policy.getExternalImplicitGroup();
             if (eig != null) { // peers are in EIG
-                if (!epLocInfo.hasRelativeLocation(peerContEpKey)) {
+                if (!currentState.epLocInfo.hasRelativeLocation(peerContEpKey)) {
                     LOG.debug("EIG Containment Peer does not have relative location therefore it is ignored: {}",
                             peerContEpKey);
                     continue;
@@ -328,7 +439,7 @@ public class RendererManager implements AutoCloseable {
                 PeerExternalContainmentEndpointKey peerExtContEpKey =
                         ContainmentEndpointUtils.toPeerExtContEpKey(peerContEpKey);
                 for (PolicyRuleGroupWithEndpointConstraints ruleGrpsWithEpConstraints : policy
-                    .getPolicyRuleGroupWithEndpointConstraints()) {
+                        .getPolicyRuleGroupWithEndpointConstraints()) {
                     // TODO filter based on endpoint constraints
                     for (PolicyRuleGroup ruleGrp : ruleGrpsWithEpConstraints.getPolicyRuleGroup()) {
                         rendererPolicyBuilder.add(rendererEpKey, peerExtContEpKey, ruleGrp.getKey(),
@@ -343,23 +454,26 @@ public class RendererManager implements AutoCloseable {
     }
 
     private void resolveRendererPolicyBetweenEpAndPeers(RendererEndpointKey rendererEpKey,
-            Set<AddressEndpointKey> peerAdrEps, ResolvedPolicy policy,
-            EndpointPolicyParticipation rendererEpParticipation, RendererConfigurationBuilder rendererPolicyBuilder) {
+                                                        Set<AddressEndpointKey> peerAdrEps, ResolvedPolicy policy,
+                                                        EndpointPolicyParticipation rendererEpParticipation, RendererConfigurationBuilder rendererPolicyBuilder) {
         if (isRendererEpInEig(policy, rendererEpParticipation)) {
             LOG.info("Renderer EP cannot be in EIG therefore it is ignored: {}. \nPolicy: {}", rendererEpKey);
             LOG.debug("Renderer EP participation: {}, Policy: {}", rendererEpParticipation, policy);
             return;
         }
         for (AddressEndpointKey peerAdrEpKey : peerAdrEps) {
+            if (isSameKeys(rendererEpKey, peerAdrEpKey)) {
+                continue;
+            }
             ExternalImplicitGroup eig = policy.getExternalImplicitGroup();
             if (eig != null) {
-                if (!epLocInfo.hasRelativeLocation(peerAdrEpKey)) {
+                if (!currentState.epLocInfo.hasRelativeLocation(peerAdrEpKey)) {
                     LOG.debug("EIG Peer does not have relative location therefore it is ignored: {}", peerAdrEpKey);
                     continue;
                 }
                 PeerExternalEndpointKey peerExtEpKey = AddressEndpointUtils.toPeerExtEpKey(peerAdrEpKey);
                 for (PolicyRuleGroupWithEndpointConstraints ruleGrpsWithEpConstraints : policy
-                    .getPolicyRuleGroupWithEndpointConstraints()) {
+                        .getPolicyRuleGroupWithEndpointConstraints()) {
                     // TODO filter based on endpoint constraints
                     for (PolicyRuleGroup ruleGrp : ruleGrpsWithEpConstraints.getPolicyRuleGroup()) {
                         rendererPolicyBuilder.add(rendererEpKey, peerExtEpKey, ruleGrp.getKey(),
@@ -367,13 +481,13 @@ public class RendererManager implements AutoCloseable {
                     }
                 }
             } else {
-                if (!epLocInfo.hasRealLocation(peerAdrEpKey)) {
-                    LOG.debug("Peer does not have real location therefore it is ignored: {}", peerAdrEpKey);
+                if (!currentState.epLocInfo.hasAbsoluteLocation(peerAdrEpKey)) {
+                    LOG.debug("Peer does not have absolute location therefore it is ignored: {}", peerAdrEpKey);
                     continue;
                 }
                 PeerEndpointKey peerEpKey = AddressEndpointUtils.toPeerEpKey(peerAdrEpKey);
                 for (PolicyRuleGroupWithEndpointConstraints ruleGrpsWithEpConstraints : policy
-                    .getPolicyRuleGroupWithEndpointConstraints()) {
+                        .getPolicyRuleGroupWithEndpointConstraints()) {
                     // TODO filter based on endpoint constraints
                     for (PolicyRuleGroup ruleGrp : ruleGrpsWithEpConstraints.getPolicyRuleGroup()) {
                         rendererPolicyBuilder.add(rendererEpKey, peerEpKey, ruleGrp.getKey(), rendererEpParticipation);
@@ -395,6 +509,16 @@ public class RendererManager implements AutoCloseable {
         return false;
     }
 
+    private boolean isSameKeys(RendererEndpointKey rendererEpKey, AddressEndpointKey peerAdrEpKey) {
+        if (rendererEpKey.getAddress().equals(peerAdrEpKey.getAddress())
+                && rendererEpKey.getAddressType().equals(peerAdrEpKey.getAddressType())
+                && rendererEpKey.getContextId().equals(peerAdrEpKey.getContextId())
+                && rendererEpKey.getContextType().equals(peerAdrEpKey.getContextType())) {
+            return true;
+        }
+        return false;
+    }
+
     private Set<EpgKeyDto> toEpgKeys(List<EndpointGroupId> epgIds, TenantId tenantId) {
         return FluentIterable.from(epgIds).transform(new Function<EndpointGroupId, EpgKeyDto>() {
 
@@ -416,12 +540,16 @@ public class RendererManager implements AutoCloseable {
     }
 
     @Override
-    public void close() throws Exception {
-        endpointsListener.close();
-        endpointLocationsListener.close();
-        resolvedPoliciesListener.close();
-        forwardingListener.close();
-        renderersListener.close();
+    public void close() {
+        try {
+            endpointsListener.close();
+            endpointLocationsListener.close();
+            resolvedPoliciesListener.close();
+            forwardingListener.close();
+            renderersListener.close();
+        } catch (Exception e) {
+            LOG.warn("Exception while closing", e);
+        }
     }
 
 }