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