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