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