2 * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
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
9 package org.opendaylight.groupbasedpolicy.renderer;
11 import static com.google.common.base.Preconditions.checkNotNull;
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;
21 import javax.annotation.Nullable;
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;
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;
79 public class RendererManager implements AutoCloseable {
81 private static final Logger LOG = LoggerFactory.getLogger(RendererManager.class);
83 private static long version = 0;
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;
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;
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);
108 public synchronized void endpointsUpdated(final Endpoints endpoints) {
109 epInfo = new EndpointInfo(endpoints);
113 public synchronized void endpointLocationsUpdated(final EndpointLocations epLocations) {
114 epLocInfo = new EndpointLocationInfo(epLocations);
118 public synchronized void resolvedPoliciesUpdated(final ResolvedPolicies resolvedPolicies) {
119 policyInfo = new ResolvedPolicyInfo(resolvedPolicies);
123 public synchronized void forwardingUpdated(final Forwarding forwarding) {
124 this.forwarding = forwarding;
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));
137 if (processingRenderers.isEmpty()) {
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);
155 LOG.debug("Renderer {} configured policy with version {} successfully.",
156 configuredRenderer.getValue(), version);
163 private void processState() {
164 if (!processingRenderers.isEmpty()) {
165 LOG.debug("Waiting for renderers. Version {} needs to be processed by renderers: {}", version,
166 processingRenderers);
169 if (rendererByNode.values().isEmpty()) {
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);
184 new RendererPolicyBuilder().setVersion(version).setConfiguration(potentialConfig.get()).build();
187 new RendererPolicyBuilder().setVersion(version).build();
189 renderers.add(new RendererBuilder().setName(rendererName).setRendererPolicy(rendererPolicy).build());
190 processingRenderers.add(rendererName);
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.",
198 for (RendererName rendererName : rendererConfigBuilderByRendererName.keySet()) {
199 processingRenderers.remove(rendererName);
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
212 private Map<RendererName, RendererConfigurationBuilder> createRendererConfigBuilders() {
213 if (!isStateValid()) {
214 return Collections.emptyMap();
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);
223 RendererConfigurationBuilder rendererConfigBuilder = rendererConfigBuilderByRendererName.get(rendererName);
224 if (rendererConfigBuilder == null) {
225 rendererConfigBuilder = new RendererConfigurationBuilder();
226 rendererConfigBuilderByRendererName.put(rendererName, rendererConfigBuilder);
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);
234 AddressEndpoint rendererAdrEp = potentialAddressEp.get();
235 resolveRendererConfigForEndpoint(rendererAdrEp, rendererConfigBuilder);
238 return rendererConfigBuilderByRendererName;
241 private boolean isStateValid() {
242 if (rendererByNode.isEmpty() || policyInfo == null || epInfo == null || epLocInfo == null
243 || forwarding == null) {
249 private Optional<Configuration> createConfiguration(@Nullable RendererConfigurationBuilder rendererPolicyBuilder) {
250 if (rendererPolicyBuilder == null) {
251 return Optional.absent();
253 ConfigurationBuilder configBuilder = new ConfigurationBuilder();
254 RendererEndpoints rendererEndpoints = rendererPolicyBuilder.buildRendererEndpoints();
255 if (isRendererEndpointsEmpty(rendererEndpoints)) {
256 return Optional.absent();
258 configBuilder.setRendererEndpoints(rendererEndpoints);
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);
264 RuleGroups ruleGroups = rendererPolicyBuilder.buildRuluGroups(policyInfo);
265 configBuilder.setRuleGroups(ruleGroups);
267 ForwardingContexts forwardingContexts = rendererPolicyBuilder.buildForwardingContexts(forwarding);
268 configBuilder.setForwardingContexts(forwardingContexts);
270 return Optional.of(configBuilder.build());
273 private boolean isRendererEndpointsEmpty(RendererEndpoints rendererEndpoints) {
274 if (rendererEndpoints == null || rendererEndpoints.getRendererEndpoint() == null
275 || rendererEndpoints.getRendererEndpoint().isEmpty()) {
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);
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);
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);
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: {}",
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);
339 LOG.info("Peer Containment EP cannot be in other EPG than EIG therefore it is ignored: {}",
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);
353 for (AddressEndpointKey peerAdrEpKey : peerAdrEps) {
354 ExternalImplicitGroup eig = policy.getExternalImplicitGroup();
356 if (!epLocInfo.hasRelativeLocation(peerAdrEpKey)) {
357 LOG.debug("EIG Peer does not have relative location therefore it is ignored: {}", peerAdrEpKey);
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);
370 if (!epLocInfo.hasRealLocation(peerAdrEpKey)) {
371 LOG.debug("Peer does not have real location therefore it is ignored: {}", peerAdrEpKey);
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);
386 private boolean isRendererEpInEig(ResolvedPolicy policy, EndpointPolicyParticipation rendererEpParticipation) {
387 ExternalImplicitGroup eig = policy.getExternalImplicitGroup();
388 if (rendererEpParticipation == EndpointPolicyParticipation.PROVIDER
389 && ExternalImplicitGroup.ProviderEpg == eig) {
391 } else if (rendererEpParticipation == EndpointPolicyParticipation.CONSUMER
392 && ExternalImplicitGroup.ConsumerEpg == eig) {
398 private Set<EpgKeyDto> toEpgKeys(List<EndpointGroupId> epgIds, TenantId tenantId) {
399 return FluentIterable.from(epgIds).transform(new Function<EndpointGroupId, EpgKeyDto>() {
402 public EpgKeyDto apply(EndpointGroupId input) {
403 return new EpgKeyDto(input, tenantId);
409 Set<RendererName> getProcessingRenderers() {
410 return processingRenderers;
414 static void resetVersion() {
419 public void close() throws Exception {
420 endpointsListener.close();
421 endpointLocationsListener.close();
422 resolvedPoliciesListener.close();
423 forwardingListener.close();
424 renderersListener.close();