Merge "ios-xe-renderer node manager update"
[groupbasedpolicy.git] / groupbasedpolicy / src / main / java / org / opendaylight / groupbasedpolicy / renderer / RendererManager.java
1 /*
2  * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.groupbasedpolicy.renderer;
10
11 import static com.google.common.base.Preconditions.checkNotNull;
12
13 import java.util.ArrayList;
14 import java.util.Collections;
15 import java.util.HashMap;
16 import java.util.HashSet;
17 import java.util.List;
18 import java.util.Map;
19 import java.util.Set;
20
21 import javax.annotation.Nullable;
22
23 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
24 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
25 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
26 import org.opendaylight.groupbasedpolicy.base_endpoint.EndpointAugmentorRegistryImpl;
27 import org.opendaylight.groupbasedpolicy.dto.ConsEpgKey;
28 import org.opendaylight.groupbasedpolicy.dto.EpgKeyDto;
29 import org.opendaylight.groupbasedpolicy.dto.ProvEpgKey;
30 import org.opendaylight.groupbasedpolicy.forwarding.NetworkDomainAugmentorRegistryImpl;
31 import org.opendaylight.groupbasedpolicy.renderer.listener.EndpointLocationsListener;
32 import org.opendaylight.groupbasedpolicy.renderer.listener.EndpointsListener;
33 import org.opendaylight.groupbasedpolicy.renderer.listener.ForwardingListener;
34 import org.opendaylight.groupbasedpolicy.renderer.listener.RenderersListener;
35 import org.opendaylight.groupbasedpolicy.renderer.listener.ResolvedPoliciesListener;
36 import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.EndpointLocations;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.Endpoints;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpoint;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpointKey;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.containment.endpoints.ContainmentEndpointKey;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.Forwarding;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.EndpointPolicyParticipation;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.RendererName;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.Renderers;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.RenderersBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.has.peer.endpoints.PeerEndpointKey;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.has.peer.external.containment.endpoints.PeerExternalContainmentEndpointKey;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.has.peer.external.endpoints.PeerExternalEndpointKey;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.Renderer;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.RendererBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.RendererPolicy;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.RendererPolicyBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.Configuration;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.ConfigurationBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.Status;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.RendererEndpoints;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.RendererForwarding;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.RuleGroups;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.endpoints.RendererEndpointKey;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.ResolvedPolicies;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.ResolvedPolicy;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.ResolvedPolicy.ExternalImplicitGroup;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.resolved.policy.PolicyRuleGroupWithEndpointConstraints;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.resolved.policy.rev150828.resolved.policies.resolved.policy.policy.rule.group.with.endpoint.constraints.PolicyRuleGroup;
68 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
69 import org.slf4j.Logger;
70 import org.slf4j.LoggerFactory;
71
72 import com.google.common.annotations.VisibleForTesting;
73 import com.google.common.base.Function;
74 import com.google.common.base.Optional;
75 import com.google.common.collect.FluentIterable;
76 import com.google.common.collect.ImmutableCollection;
77 import com.google.common.collect.ImmutableMap;
78 import com.google.common.collect.ImmutableMultimap;
79 import com.google.common.collect.ImmutableSet;
80
81 public class RendererManager implements AutoCloseable {
82
83     private static final Logger LOG = LoggerFactory.getLogger(RendererManager.class);
84
85     private static long version = 0;
86
87     private final DataBroker dataProvider;
88     private final NetworkDomainAugmentorRegistryImpl netDomainAugmentorRegistry;
89     private final EndpointAugmentorRegistryImpl epAugmentorRegistry;
90     private final Set<RendererName> processingRenderers = new HashSet<>();
91     private Map<InstanceIdentifier<?>, RendererName> rendererByNode = new HashMap<>();
92     private ResolvedPolicyInfo policyInfo;
93     private EndpointInfo epInfo;
94     private EndpointLocationInfo epLocInfo;
95     private Forwarding forwarding;
96     private boolean changesWaitingToProcess = false;
97     private boolean currentVersionHasConfig = false;
98
99     private final EndpointsListener endpointsListener;
100     private final EndpointLocationsListener endpointLocationsListener;
101     private final ResolvedPoliciesListener resolvedPoliciesListener;
102     private final ForwardingListener forwardingListener;
103     private final RenderersListener renderersListener;
104
105     public RendererManager(DataBroker dataProvider, NetworkDomainAugmentorRegistryImpl netDomainAugmentorRegistry,
106             EndpointAugmentorRegistryImpl epAugmentorRegistry) {
107         this.dataProvider = checkNotNull(dataProvider);
108         this.netDomainAugmentorRegistry = checkNotNull(netDomainAugmentorRegistry);
109         this.epAugmentorRegistry = checkNotNull(epAugmentorRegistry);
110         endpointsListener = new EndpointsListener(this, dataProvider);
111         endpointLocationsListener = new EndpointLocationsListener(this, dataProvider);
112         resolvedPoliciesListener = new ResolvedPoliciesListener(this, dataProvider);
113         forwardingListener = new ForwardingListener(this, dataProvider);
114         renderersListener = new RenderersListener(this, dataProvider);
115     }
116
117     public synchronized void endpointsUpdated(final Endpoints endpoints) {
118         epInfo = new EndpointInfo(endpoints);
119         changesWaitingToProcess = true;
120         processState();
121     }
122
123     public synchronized void endpointLocationsUpdated(final EndpointLocations epLocations) {
124         epLocInfo = new EndpointLocationInfo(epLocations);
125         changesWaitingToProcess = true;
126         processState();
127     }
128
129     public synchronized void resolvedPoliciesUpdated(final ResolvedPolicies resolvedPolicies) {
130         policyInfo = new ResolvedPolicyInfo(resolvedPolicies);
131         changesWaitingToProcess = true;
132         processState();
133     }
134
135     public synchronized void forwardingUpdated(final Forwarding forwarding) {
136         this.forwarding = forwarding;
137         changesWaitingToProcess = true;
138         processState();
139     }
140
141     public synchronized void renderersUpdated(final Renderers renderersCont) {
142         ImmutableMultimap<InstanceIdentifier<?>, RendererName> renderersByNode =
143                 RendererUtils.resolveRenderersByNodes(renderersCont.getRenderer());
144         rendererByNode = new HashMap<>();
145         for (InstanceIdentifier<?> nodePath : renderersByNode.keySet()) {
146             ImmutableCollection<RendererName> renderers = renderersByNode.get(nodePath);
147             // only first renderer is used
148             rendererByNode.put(nodePath, renderers.asList().get(0));
149         }
150         if (processingRenderers.isEmpty()) {
151             changesWaitingToProcess = true;
152         } else {
153             LOG.debug("Waiting for renderers. Version {} needs to be processed by renderers: {}", version,
154                     processingRenderers);
155             ImmutableMap<RendererName, Renderer> rendererByName =
156                     RendererUtils.resolveRendererByName(renderersCont.getRenderer());
157             for (RendererName configuredRenderer : processingRenderers) {
158                 Renderer renderer = rendererByName.get(configuredRenderer);
159                 RendererPolicy rendererPolicy = renderer.getRendererPolicy();
160                 if (rendererPolicy != null && rendererPolicy.getVersion() != null
161                         && renderer.getRendererPolicy().getVersion().equals(version)) {
162                     processingRenderers.remove(configuredRenderer);
163                     Status status = rendererPolicy.getStatus();
164                     if (status != null && status.getUnconfiguredRule() != null) {
165                         LOG.warn("Renderer {} did not configure policy with version {} successfully. \n{}",
166                                 configuredRenderer.getValue(), version, status);
167                     } else {
168                         LOG.debug("Renderer {} configured policy with version {} successfully.",
169                                 configuredRenderer.getValue(), version);
170                     }
171                 }
172             }
173         }
174         processState();
175     }
176
177     private void processState() {
178         if (!processingRenderers.isEmpty()) {
179             LOG.debug("Waiting for renderers. Version {} needs to be processed by renderers: {}", version,
180                     processingRenderers);
181             return;
182         }
183         if (rendererByNode.values().isEmpty()) {
184             return;
185         }
186         if (!changesWaitingToProcess) {
187             return;
188         }
189         Map<RendererName, RendererConfigurationBuilder> rendererConfigBuilderByRendererName = createRendererConfigBuilders();
190         Set<RendererName> rendererNames = new HashSet<>(rendererByNode.values());
191         boolean newVersionHasConfig = false;
192         Map<RendererName, Optional<Configuration>> configsByRendererName = new HashMap<>();
193         for (RendererName rendererName : rendererNames) {
194             RendererConfigurationBuilder rendererPolicyBuilder = rendererConfigBuilderByRendererName.get(rendererName);
195             Optional<Configuration> potentialConfig = createConfiguration(rendererPolicyBuilder);
196             if (potentialConfig.isPresent()) {
197                 newVersionHasConfig = true;
198             }
199             configsByRendererName.put(rendererName, potentialConfig);
200         }
201         if (newVersionHasConfig || currentVersionHasConfig) {
202             version++;
203             if (!writeRenderersConfigs(configsByRendererName)) {
204                 LOG.warn("Version {} was not dispatched successfully. Previous version is valid until next update.",
205                         version);
206                 for (RendererName rendererName : rendererConfigBuilderByRendererName.keySet()) {
207                     processingRenderers.remove(rendererName);
208                 }
209                 version--;
210                 changesWaitingToProcess = true;
211                 return;
212             } else {
213                 currentVersionHasConfig = newVersionHasConfig;
214             }
215         }
216         changesWaitingToProcess = false;
217     }
218
219     private boolean writeRenderersConfigs(Map<RendererName, Optional<Configuration>> configsByRendererName) {
220         List<Renderer> renderers = new ArrayList<>();
221         for (RendererName rendererName : configsByRendererName.keySet()) {
222             RendererPolicy rendererPolicy = null;
223             if (configsByRendererName.get(rendererName).isPresent()) {
224                 rendererPolicy = new RendererPolicyBuilder().setVersion(version)
225                     .setConfiguration(configsByRendererName.get(rendererName).get())
226                     .build();
227
228             } else {
229                 rendererPolicy = new RendererPolicyBuilder().setVersion(version).build();
230             }
231             renderers.add(new RendererBuilder().setName(rendererName).setRendererPolicy(rendererPolicy).build());
232             processingRenderers.add(rendererName);
233             LOG.debug("Created configuration for renderer {} with version {}", rendererName.getValue(), version);
234         }
235         WriteTransaction wTx = dataProvider.newWriteOnlyTransaction();
236         wTx.put(LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.create(Renderers.class),
237                 new RenderersBuilder().setRenderer(renderers).build());
238         return DataStoreHelper.submitToDs(wTx);
239     }
240
241     /**
242      * Entry is added to the result map only if:<br>
243      * 1. There is at least one Address EP with absolute location
244      * 2. There is a renderer responsible for that EP
245      *
246      * @return
247      */
248     private Map<RendererName, RendererConfigurationBuilder> createRendererConfigBuilders() {
249         if (!isStateValid()) {
250             return Collections.emptyMap();
251         }
252         Map<RendererName, RendererConfigurationBuilder> rendererConfigBuilderByRendererName = new HashMap<>();
253         for (InstanceIdentifier<?> absEpLocation : epLocInfo.getAllAbsoluteNodeLocations()) {
254             RendererName rendererName = rendererByNode.get(absEpLocation);
255             if (rendererName == null) {
256                 LOG.trace("Renderer does not exist for EP with location: {}", absEpLocation);
257                 continue;
258             }
259             RendererConfigurationBuilder rendererConfigBuilder = rendererConfigBuilderByRendererName.get(rendererName);
260             if (rendererConfigBuilder == null) {
261                 rendererConfigBuilder = new RendererConfigurationBuilder();
262                 rendererConfigBuilderByRendererName.put(rendererName, rendererConfigBuilder);
263             }
264             for (AddressEndpointKey rendererAdrEpKey : epLocInfo.getAddressEpsWithAbsoluteNodeLocation(absEpLocation)) {
265                 Optional<AddressEndpoint> potentialAddressEp = epInfo.getEndpoint(rendererAdrEpKey);
266                 if (!potentialAddressEp.isPresent()) {
267                     LOG.trace("Endpoint does not exist but has location: {}", rendererAdrEpKey);
268                     continue;
269                 }
270                 AddressEndpoint rendererAdrEp = potentialAddressEp.get();
271                 resolveRendererConfigForEndpoint(rendererAdrEp, rendererConfigBuilder);
272             }
273         }
274         return rendererConfigBuilderByRendererName;
275     }
276
277     private boolean isStateValid() {
278         if (rendererByNode.isEmpty() || policyInfo == null || epInfo == null || epLocInfo == null
279                 || forwarding == null) {
280             return false;
281         }
282         return true;
283     }
284
285     private Optional<Configuration> createConfiguration(@Nullable RendererConfigurationBuilder rendererPolicyBuilder) {
286         if (rendererPolicyBuilder == null) {
287             return Optional.absent();
288         }
289         ConfigurationBuilder configBuilder = new ConfigurationBuilder();
290         RendererEndpoints rendererEndpoints = rendererPolicyBuilder.buildRendererEndpoints();
291         if (isRendererEndpointsEmpty(rendererEndpoints)) {
292             return Optional.absent();
293         }
294         configBuilder.setRendererEndpoints(rendererEndpoints);
295
296         org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.Endpoints endpoints =
297                 rendererPolicyBuilder.buildEndoints(epInfo, epLocInfo, rendererByNode, epAugmentorRegistry.getEndpointAugmentors());
298         configBuilder.setEndpoints(endpoints);
299
300         RuleGroups ruleGroups = rendererPolicyBuilder.buildRuluGroups(policyInfo);
301         configBuilder.setRuleGroups(ruleGroups);
302
303         RendererForwarding rendererForwarding = rendererPolicyBuilder.buildRendererForwarding(forwarding,
304                 netDomainAugmentorRegistry.getNetworkDomainAugmentors());
305         configBuilder.setRendererForwarding(rendererForwarding);
306
307         return Optional.of(configBuilder.build());
308     }
309
310     private boolean isRendererEndpointsEmpty(RendererEndpoints rendererEndpoints) {
311         if (rendererEndpoints == null || rendererEndpoints.getRendererEndpoint() == null
312                 || rendererEndpoints.getRendererEndpoint().isEmpty()) {
313             return true;
314         }
315         return false;
316     }
317
318     @VisibleForTesting
319     void resolveRendererConfigForEndpoint(AddressEndpoint rendererAdrEp,
320             RendererConfigurationBuilder rendererPolicyBuilder) {
321         Set<EpgKeyDto> rendererEpgs = toEpgKeys(rendererAdrEp.getEndpointGroup(), rendererAdrEp.getTenant());
322         RendererEndpointKey rendererEpKey = AddressEndpointUtils.toRendererEpKey(rendererAdrEp.getKey());
323         for (EpgKeyDto rendererEpg : rendererEpgs) {
324             ImmutableSet<ConsEpgKey> consPeerEpgs = policyInfo.findConsumerPeers(rendererEpg);
325             for (ConsEpgKey consPeerEpg : consPeerEpgs) {
326                 Optional<ResolvedPolicy> potentialPolicy = policyInfo.findPolicy(consPeerEpg, rendererEpg);
327                 ResolvedPolicy policy = potentialPolicy.get();
328                 ImmutableSet<AddressEndpointKey> consPeerAdrEps = epInfo.findAddressEpsWithEpg(consPeerEpg);
329                 resolveRendererPolicyBetweenEpAndPeers(rendererEpKey, consPeerAdrEps, policy,
330                         EndpointPolicyParticipation.PROVIDER, rendererPolicyBuilder);
331                 ImmutableSet<ContainmentEndpointKey> consPeerContEps = epInfo.findContainmentEpsWithEpg(consPeerEpg);
332                 resolveRendererPolicyBetweenEpAndContPeers(rendererEpKey, consPeerContEps, policy,
333                         EndpointPolicyParticipation.PROVIDER, rendererPolicyBuilder);
334             }
335             ImmutableSet<ProvEpgKey> provPeerEpgs = policyInfo.findProviderPeers(rendererEpg);
336             for (ProvEpgKey provPeerEpg : provPeerEpgs) {
337                 Optional<ResolvedPolicy> potentialPolicy = policyInfo.findPolicy(rendererEpg, provPeerEpg);
338                 ResolvedPolicy policy = potentialPolicy.get();
339                 ImmutableSet<AddressEndpointKey> provPeerAdrEps = epInfo.findAddressEpsWithEpg(provPeerEpg);
340                 resolveRendererPolicyBetweenEpAndPeers(rendererEpKey, provPeerAdrEps, policy,
341                         EndpointPolicyParticipation.CONSUMER, rendererPolicyBuilder);
342                 ImmutableSet<ContainmentEndpointKey> provPeerContEps = epInfo.findContainmentEpsWithEpg(provPeerEpg);
343                 resolveRendererPolicyBetweenEpAndContPeers(rendererEpKey, provPeerContEps, policy,
344                         EndpointPolicyParticipation.CONSUMER, rendererPolicyBuilder);
345             }
346         }
347     }
348
349     private void resolveRendererPolicyBetweenEpAndContPeers(RendererEndpointKey rendererEpKey,
350             Set<ContainmentEndpointKey> peerContEps, ResolvedPolicy policy,
351             EndpointPolicyParticipation rendererEpParticipation, RendererConfigurationBuilder rendererPolicyBuilder) {
352         if (isRendererEpInEig(policy, rendererEpParticipation)) {
353             LOG.info("Renderer EP cannot be in EIG therefore it is ignored: {}. \nPolicy: {}", rendererEpKey);
354             LOG.debug("Renderer EP participation: {}, Policy: {}", rendererEpParticipation, policy);
355             return;
356         }
357         for (ContainmentEndpointKey peerContEpKey : peerContEps) {
358             ExternalImplicitGroup eig = policy.getExternalImplicitGroup();
359             if (eig != null) { // peers are in EIG
360                 if (!epLocInfo.hasRelativeLocation(peerContEpKey)) {
361                     LOG.debug("EIG Containment Peer does not have relative location therefore it is ignored: {}",
362                             peerContEpKey);
363                     continue;
364                 }
365                 PeerExternalContainmentEndpointKey peerExtContEpKey =
366                         ContainmentEndpointUtils.toPeerExtContEpKey(peerContEpKey);
367                 for (PolicyRuleGroupWithEndpointConstraints ruleGrpsWithEpConstraints : policy
368                     .getPolicyRuleGroupWithEndpointConstraints()) {
369                     // TODO filter based on endpoint constraints
370                     for (PolicyRuleGroup ruleGrp : ruleGrpsWithEpConstraints.getPolicyRuleGroup()) {
371                         rendererPolicyBuilder.add(rendererEpKey, peerExtContEpKey, ruleGrp.getKey(),
372                                 rendererEpParticipation);
373                     }
374                 }
375             } else {
376                 LOG.info("Peer Containment EP cannot be in other EPG than EIG therefore it is ignored: {}",
377                         peerContEpKey);
378             }
379         }
380     }
381
382     private void resolveRendererPolicyBetweenEpAndPeers(RendererEndpointKey rendererEpKey,
383             Set<AddressEndpointKey> peerAdrEps, ResolvedPolicy policy,
384             EndpointPolicyParticipation rendererEpParticipation, RendererConfigurationBuilder rendererPolicyBuilder) {
385         if (isRendererEpInEig(policy, rendererEpParticipation)) {
386             LOG.info("Renderer EP cannot be in EIG therefore it is ignored: {}. \nPolicy: {}", rendererEpKey);
387             LOG.debug("Renderer EP participation: {}, Policy: {}", rendererEpParticipation, policy);
388             return;
389         }
390         for (AddressEndpointKey peerAdrEpKey : peerAdrEps) {
391             if (isSameKeys(rendererEpKey, peerAdrEpKey)) {
392                 continue;
393             }
394             ExternalImplicitGroup eig = policy.getExternalImplicitGroup();
395             if (eig != null) {
396                 if (!epLocInfo.hasRelativeLocation(peerAdrEpKey)) {
397                     LOG.debug("EIG Peer does not have relative location therefore it is ignored: {}", peerAdrEpKey);
398                     continue;
399                 }
400                 PeerExternalEndpointKey peerExtEpKey = AddressEndpointUtils.toPeerExtEpKey(peerAdrEpKey);
401                 for (PolicyRuleGroupWithEndpointConstraints ruleGrpsWithEpConstraints : policy
402                     .getPolicyRuleGroupWithEndpointConstraints()) {
403                     // TODO filter based on endpoint constraints
404                     for (PolicyRuleGroup ruleGrp : ruleGrpsWithEpConstraints.getPolicyRuleGroup()) {
405                         rendererPolicyBuilder.add(rendererEpKey, peerExtEpKey, ruleGrp.getKey(),
406                                 rendererEpParticipation);
407                     }
408                 }
409             } else {
410                 if (!epLocInfo.hasRealLocation(peerAdrEpKey)) {
411                     LOG.debug("Peer does not have real location therefore it is ignored: {}", peerAdrEpKey);
412                     continue;
413                 }
414                 PeerEndpointKey peerEpKey = AddressEndpointUtils.toPeerEpKey(peerAdrEpKey);
415                 for (PolicyRuleGroupWithEndpointConstraints ruleGrpsWithEpConstraints : policy
416                     .getPolicyRuleGroupWithEndpointConstraints()) {
417                     // TODO filter based on endpoint constraints
418                     for (PolicyRuleGroup ruleGrp : ruleGrpsWithEpConstraints.getPolicyRuleGroup()) {
419                         rendererPolicyBuilder.add(rendererEpKey, peerEpKey, ruleGrp.getKey(), rendererEpParticipation);
420                     }
421                 }
422             }
423         }
424     }
425
426     private boolean isRendererEpInEig(ResolvedPolicy policy, EndpointPolicyParticipation rendererEpParticipation) {
427         ExternalImplicitGroup eig = policy.getExternalImplicitGroup();
428         if (rendererEpParticipation == EndpointPolicyParticipation.PROVIDER
429                 && ExternalImplicitGroup.ProviderEpg == eig) {
430             return true;
431         } else if (rendererEpParticipation == EndpointPolicyParticipation.CONSUMER
432                 && ExternalImplicitGroup.ConsumerEpg == eig) {
433             return true;
434         }
435         return false;
436     }
437
438     private boolean isSameKeys(RendererEndpointKey rendererEpKey, AddressEndpointKey peerAdrEpKey) {
439         if (rendererEpKey.getAddress().equals(peerAdrEpKey.getAddress())
440                 && rendererEpKey.getAddressType().equals(peerAdrEpKey.getAddressType())
441                 && rendererEpKey.getContextId().equals(peerAdrEpKey.getContextId())
442                 && rendererEpKey.getContextType().equals(peerAdrEpKey.getContextType())) {
443             return true;
444         }
445         return false;
446     }
447
448     private Set<EpgKeyDto> toEpgKeys(List<EndpointGroupId> epgIds, TenantId tenantId) {
449         return FluentIterable.from(epgIds).transform(new Function<EndpointGroupId, EpgKeyDto>() {
450
451             @Override
452             public EpgKeyDto apply(EndpointGroupId input) {
453                 return new EpgKeyDto(input, tenantId);
454             }
455         }).toSet();
456     }
457
458     @VisibleForTesting
459     Set<RendererName> getProcessingRenderers() {
460         return processingRenderers;
461     }
462
463     @VisibleForTesting
464     static void resetVersion() {
465         version = 0;
466     }
467
468     @Override
469     public void close() throws Exception {
470         endpointsListener.close();
471         endpointLocationsListener.close();
472         resolvedPoliciesListener.close();
473         forwardingListener.close();
474         renderersListener.close();
475     }
476
477 }