2 * Copyright (c) 2014 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.resolver;
11 import java.util.ArrayList;
12 import java.util.Collections;
13 import java.util.HashMap;
14 import java.util.List;
16 import java.util.concurrent.ConcurrentHashMap;
17 import java.util.concurrent.ConcurrentMap;
18 import java.util.concurrent.CopyOnWriteArrayList;
19 import java.util.concurrent.ScheduledExecutorService;
20 import java.util.concurrent.atomic.AtomicReference;
22 import javax.annotation.concurrent.Immutable;
24 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
25 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
26 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
27 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
28 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
29 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
30 import org.opendaylight.groupbasedpolicy.resolver.PolicyCache.ConditionSet;
31 import org.opendaylight.groupbasedpolicy.resolver.PolicyCache.Policy;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ConditionName;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContractId;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubjectName;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.ConsumerSelectionRelator;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.Matcher.MatchType;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.ProviderSelectionRelator;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.condition.matchers.ConditionMatcher;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.has.conditions.Condition;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.target.selector.QualityMatcher;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.Tenant;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.Contract;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.EndpointGroup;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.Clause;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.Subject;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.Target;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.consumer.matchers.RequirementMatcher;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.clause.provider.matchers.CapabilityMatcher;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.contract.subject.Rule;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ConsumerNamedSelector;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ConsumerTargetSelector;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ProviderNamedSelector;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.endpoint.group.ProviderTargetSelector;
56 import org.opendaylight.yangtools.concepts.ListenerRegistration;
57 import org.opendaylight.yangtools.yang.binding.DataObject;
58 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
59 import org.slf4j.Logger;
60 import org.slf4j.LoggerFactory;
62 import com.google.common.base.Optional;
63 import com.google.common.base.Predicate;
64 import com.google.common.collect.HashBasedTable;
65 import com.google.common.collect.ImmutableSet;
66 import com.google.common.collect.Ordering;
67 import com.google.common.collect.Sets;
68 import com.google.common.collect.Table;
69 import com.google.common.collect.Table.Cell;
70 import com.google.common.util.concurrent.FutureCallback;
71 import com.google.common.util.concurrent.Futures;
72 import com.google.common.util.concurrent.ListenableFuture;
75 * The policy resolver is a utility for renderers to help in resolving
76 * group-based policy into a form that is easier to apply to the actual network.
78 * <p>For any pair of endpoint groups, there is a set of rules that could apply
79 * to the endpoints on that group based on the policy configuration. The exact
80 * list of rules that apply to a given pair of endpoints depends on the
81 * conditions that are active on the endpoints.
83 * In a more formal sense: Let there be endpoint groups G_n, and for each G_n a
84 * set of conditions C_n that can apply to endpoints in G_n. Further, let S be
85 * the set of lists of rules defined in the policy. Our policy can be
86 * represented as a function F: (G_n, 2^C_n, G_m, 2^C_m) -> S, where 2^C_n
87 * represents the power set of C_n. In other words, we want to map all the
88 * possible tuples of pairs of endpoints along with their active conditions
89 * onto the right list of rules to apply.
91 * <p>We need to be able to query against this policy model, enumerate the
92 * relevant classes of traffic and endpoints, and notify renderers when there
93 * are changes to policy as it applies to active sets of endpoints and
96 * <p>The policy resolver will maintain the necessary state for all tenants
97 * in its control domain, which is the set of tenants for which
98 * policy listeners have been registered.
102 public class PolicyResolver implements AutoCloseable {
103 private static final Logger LOG = LoggerFactory.getLogger(PolicyResolver.class);
105 private final DataBroker dataProvider;
106 private final ScheduledExecutorService executor;
109 * Keep track of the current relevant policy scopes.
111 private CopyOnWriteArrayList<PolicyScope> policyListenerScopes;
113 private ConcurrentMap<TenantId, TenantContext> resolvedTenants;
115 private PolicyCache policyCache = new PolicyCache();
117 public PolicyResolver(DataBroker dataProvider,
118 ScheduledExecutorService executor) {
120 this.dataProvider = dataProvider;
121 this.executor = executor;
122 policyListenerScopes = new CopyOnWriteArrayList<>();
123 resolvedTenants = new ConcurrentHashMap<>();
125 LOG.debug("Initialized renderer common policy resolver");
133 public void close() throws Exception {
134 for (TenantContext ctx : resolvedTenants.values()) {
135 if (ctx.registration != null)
136 ctx.registration.close();
140 // *************************
141 // PolicyResolver public API
142 // *************************
145 * Get the policy that currently applies to a pair of endpoints.
146 * with the specified groups and conditions. The first endpoint acts as
147 * the consumer and the second endpoint acts as the provider, so to get
148 * all policy related to this pair of endpoints you must call this
149 * function twice: once for each possible order of endpoints.
151 * @param ep1Tenant the tenant ID for the first endpoint
152 * @param ep1Group the endpoint group for the first endpoint
153 * @param ep1Conds The conditions that apply to the first endpoint
154 * @param ep2Tenant the tenant ID for the second endpoint
155 * @param ep2Group the endpoint group for the second endpoint
156 * @param ep2Conds The conditions that apply to the second endpoint.
157 * @return a list of {@link RuleGroup} that apply to the endpoints.
158 * Cannot be null, but may be an empty list of rulegroups
160 public List<RuleGroup> getPolicy(TenantId ep1Tenant,
161 EndpointGroupId ep1Group,
162 ConditionSet ep1Conds,
164 EndpointGroupId ep2Group,
165 ConditionSet ep2Conds) {
166 return policyCache.getPolicy(ep1Tenant, ep1Group, ep1Conds,
167 ep2Tenant, ep2Group, ep2Conds);
171 * Register a listener to receive update events.
172 * @param listener the {@link PolicyListener} object to receive the update
175 public PolicyScope registerListener(PolicyListener listener) {
176 PolicyScope ps = new PolicyScope(this, listener);
177 policyListenerScopes.add(ps);
183 * Remove the listener registered for the given {@link PolicyScope}.
184 * @param scope the scope to remove
185 * @see PolicyResolver#registerListener(PolicyListener)
187 public void removeListener(PolicyScope scope) {
188 policyListenerScopes.remove(scope);
196 * Notify the policy listeners about a set of updated consumers
198 private void notifyListeners(Set<EgKey> updatedConsumers) {
199 for (final PolicyScope scope : policyListenerScopes) {
200 Set<EgKey> filtered =
201 Sets.filter(updatedConsumers, new Predicate<EgKey>() {
203 public boolean apply(EgKey input) {
204 return scope.contains(input.getTenantId(),
208 if (!filtered.isEmpty()) {
209 scope.getListener().policyUpdated(filtered);
215 * Subscribe the resolver to updates related to a particular tenant
216 * Make sure that this can't be called concurrently with subscribe
217 * @param tenantId the tenant ID to subscribe to
219 protected void subscribeTenant(TenantId tenantId) {
220 if (!resolvedTenants.containsKey(tenantId))
221 updateTenant(tenantId);
225 * Unsubscribe the resolver from updates related to a particular tenant
226 * Make sure that this can't be called concurrently with subscribe
227 * @param tenantId the tenant ID to subscribe to
229 protected void unsubscribeTenant(TenantId tenantId) {
230 TenantContext context = resolvedTenants.get(tenantId);
231 if (context != null) {
232 resolvedTenants.remove(tenantId);
233 context.registration.close();
237 private void updateTenant(final TenantId tenantId) {
238 TenantContext context = resolvedTenants.get(tenantId);
239 if (context == null) {
240 ListenerRegistration<DataChangeListener> registration =
241 dataProvider.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
242 TenantUtils.tenantIid(tenantId),
243 new PolicyChangeListener(tenantId),
244 DataChangeScope.SUBTREE);
246 context = new TenantContext(tenantId, registration);
247 TenantContext oldContext =
248 resolvedTenants.putIfAbsent(tenantId, context);
249 if (oldContext != null) {
250 // already registered in a different thread; just use the other
252 registration.close();
253 context = oldContext;
257 // Resolve the new tenant and update atomically
258 final AtomicReference<Tenant> tenantRef = context.tenant;
259 final Tenant ot = tenantRef.get();
260 ReadOnlyTransaction transaction =
261 dataProvider.newReadOnlyTransaction();
262 InstanceIdentifier<Tenant> tiid = TenantUtils.tenantIid(tenantId);
263 ListenableFuture<Optional<DataObject>> unresolved;
265 unresolved = transaction.read(LogicalDatastoreType.CONFIGURATION, tiid);
267 Futures.addCallback(unresolved, new FutureCallback<Optional<DataObject>>() {
269 public void onSuccess(Optional<DataObject> result) {
270 if (!result.isPresent()) return;
272 Tenant t = InheritanceUtils.resolveTenant((Tenant)result.get());
273 if (!tenantRef.compareAndSet(ot, t)) {
274 // concurrent update of tenant policy. Retry
275 updateTenant(tenantId);
277 // Update the policy cache and notify listeners
278 Table<EgKey, EgKey, Policy> policy = resolvePolicy(t);
279 Set<EgKey> updatedConsumers =
280 policyCache.updatePolicy(policy, policyListenerScopes);
282 notifyListeners(updatedConsumers);
287 public void onFailure(Throwable t) {
288 LOG.error("Count not get tenant {}", tenantId, t);
295 * Resolve the policy in three phases:
296 * (1) select contracts that in scope based on contract selectors.
297 * (2) select subjects that are in scope for each contract based on
298 * matchers in clauses
299 * (3) resolve the set of in-scope contracts into a list of subjects that
300 * apply for each pair of endpoint groups and the conditions that can
301 * apply for for each endpoint in those groups.
303 protected Table<EgKey, EgKey, Policy> resolvePolicy(Tenant t) {
304 // select contracts that apply for the given tenant
305 Table<EgKey, EgKey, List<ContractMatch>> contractMatches =
308 // select subjects for the matching contracts and resolve the policy
309 // for endpoint group pairs. This does phase (2) and (3) as one step
310 return selectSubjects(contractMatches);
314 * Choose the contracts that are in scope for each pair of endpoint
315 * groups, then perform subject selection for the pair
317 protected Table<EgKey, EgKey, List<ContractMatch>>
318 selectContracts(Tenant tenant) {
319 // For each endpoint group, match consumer selectors
320 // against contracts to get a set of matching consumer selectors
321 Table<TenantId, ContractId, List<ConsumerContractMatch>> consumerMatches =
322 HashBasedTable.create();
323 if (tenant.getEndpointGroup() == null) return HashBasedTable.create();
324 for (EndpointGroup group : tenant.getEndpointGroup()) {
325 List<ConsumerContractMatch> r =
326 matchConsumerContracts(tenant, group);
327 for (ConsumerContractMatch ccm : r) {
328 List<ConsumerContractMatch> cms =
329 consumerMatches.get(tenant.getId(),
330 ccm.contract.getId());
332 cms = new ArrayList<>();
333 consumerMatches.put(tenant.getId(),
334 ccm.contract.getId(), cms);
340 // Match provider selectors, and check each match for a corresponding
341 // consumer selector match.
342 Table<EgKey, EgKey, List<ContractMatch>> contractMatches =
343 HashBasedTable.create();
344 for (EndpointGroup group : tenant.getEndpointGroup()) {
345 List<ContractMatch> matches =
346 matchProviderContracts(tenant, group, consumerMatches);
347 for (ContractMatch cm : matches) {
348 EgKey consumerKey = new EgKey(cm.consumerTenant.getId(),
349 cm.consumer.getId());
350 EgKey providerKey = new EgKey(cm.providerTenant.getId(),
351 cm.provider.getId());
352 List<ContractMatch> egPairMatches =
353 contractMatches.get(consumerKey, providerKey);
354 if (egPairMatches == null) {
355 egPairMatches = new ArrayList<>();
356 contractMatches.put(consumerKey, providerKey,
360 egPairMatches.add(cm);
363 return contractMatches;
366 private boolean clauseMatches(Clause clause, ContractMatch match) {
367 if (clause.getConsumerMatchers() != null) {
368 List<RequirementMatcher> reqMatchers =
369 clause.getConsumerMatchers().getRequirementMatcher();
370 if (reqMatchers != null) {
371 for (RequirementMatcher reqMatcher : reqMatchers) {
372 if (!MatcherUtils.applyReqMatcher(reqMatcher,
373 match.consumerRelator)) {
379 if (clause.getProviderMatchers() != null) {
380 List<CapabilityMatcher> capMatchers =
381 clause.getProviderMatchers().getCapabilityMatcher();
382 if (capMatchers != null) {
383 for (CapabilityMatcher capMatcher : capMatchers) {
384 if (!MatcherUtils.applyCapMatcher(capMatcher,
385 match.providerRelator)) {
394 private ConditionSet buildConditionSet(List<ConditionMatcher> condMatchers) {
395 if (condMatchers == null) return ConditionSet.EMPTY;
397 ImmutableSet.Builder<ConditionName> allb = ImmutableSet.builder();
398 ImmutableSet.Builder<ConditionName> noneb = ImmutableSet.builder();
399 ImmutableSet.Builder<Set<ConditionName>> anyb =
400 ImmutableSet.builder();
401 for (ConditionMatcher condMatcher : condMatchers) {
402 if (condMatcher.getCondition() == null)
404 MatchType type = condMatcher.getMatchType();
405 if (type == null) type = MatchType.All;
406 if (type.equals(MatchType.Any)) {
407 ImmutableSet.Builder<ConditionName> a =
408 ImmutableSet.builder();
409 for (Condition c : condMatcher.getCondition()) {
414 for (Condition c : condMatcher.getCondition()) {
419 noneb.add(c.getName());
423 allb.add(c.getName());
429 return new ConditionSet(allb.build(), noneb.build(), anyb.build());
432 private ConditionSet buildConsConditionSet(Clause clause) {
433 if (clause.getConsumerMatchers() != null) {
434 List<ConditionMatcher> condMatchers =
435 clause.getConsumerMatchers().getConditionMatcher();
436 return buildConditionSet(condMatchers);
438 return ConditionSet.EMPTY;
441 private ConditionSet buildProvConditionSet(Clause clause) {
442 if (clause.getProviderMatchers() != null) {
443 List<ConditionMatcher> condMatchers =
444 clause.getProviderMatchers().getConditionMatcher();
445 return buildConditionSet(condMatchers);
447 return ConditionSet.EMPTY;
450 private Policy resolvePolicy(Tenant contractTenant,
453 Table<ConditionSet, ConditionSet, List<Subject>> subjectMap) {
454 Table<ConditionSet, ConditionSet, List<RuleGroup>> ruleMap =
455 HashBasedTable.create();
457 ruleMap.putAll(merge.ruleMap);
459 for (Cell<ConditionSet, ConditionSet, List<Subject>> entry :
460 subjectMap.cellSet()) {
461 List<RuleGroup> rules = new ArrayList<>();
462 List<RuleGroup> oldrules =
463 ruleMap.get(entry.getRowKey(), entry.getColumnKey());
464 if (oldrules != null) {
465 rules.addAll(oldrules);
467 for (Subject s : entry.getValue()) {
468 if (s.getRule() == null) continue;
469 List<Rule> srules = Ordering
470 .from(TenantUtils.RULE_COMPARATOR)
471 .immutableSortedCopy(s.getRule());
472 RuleGroup rg = new RuleGroup(srules, s.getOrder(),
473 contractTenant, contract,
477 Collections.sort(rules);
478 ruleMap.put(entry.getRowKey(), entry.getColumnKey(),
479 Collections.unmodifiableList(rules));
481 return new Policy(ruleMap);
485 * Choose the set of subjects that in scope for each possible set of
486 * endpoint conditions
488 protected Table<EgKey, EgKey, Policy>
489 selectSubjects(Table<EgKey, EgKey,
490 List<ContractMatch>> contractMatches) {
491 // Note that it's possible to further simplify the resulting policy
492 // in the case of things like repeated rules, condition sets that
493 // cover other condition sets, etc. This would be a good thing to do
495 Table<EgKey, EgKey, Policy> policy = HashBasedTable.create();
497 for (List<ContractMatch> matches : contractMatches.values()) {
498 for (ContractMatch match : matches) {
499 List<Clause> clauses = match.contract.getClause();
500 if (clauses == null) continue;
502 List<Subject> subjectList = match.contract.getSubject();
503 if (subjectList == null) continue;
505 EgKey ckey = new EgKey(match.consumerTenant.getId(),
506 match.consumer.getId());
507 EgKey pkey = new EgKey(match.providerTenant.getId(),
508 match.provider.getId());
509 Policy existing = policy.get(ckey, pkey);
510 boolean alreadyMatched = false;
511 if (existing != null) {
512 for (List<RuleGroup> rgl : existing.ruleMap.values()) {
513 for (RuleGroup rg : rgl) {
514 if (rg.relatedContract == match.contract) {
515 alreadyMatched = true;
519 if (alreadyMatched) break;
521 if (alreadyMatched) continue;
524 HashMap<SubjectName, Subject> subjects = new HashMap<>();
525 for (Subject s : subjectList) {
526 subjects.put(s.getName(), s);
529 Table<ConditionSet, ConditionSet, List<Subject>> subjectMap =
530 HashBasedTable.create();
532 for (Clause clause : clauses) {
533 if (clause.getSubjectRefs() != null &&
534 clauseMatches(clause, match)) {
535 ConditionSet consCSet = buildConsConditionSet(clause);
536 ConditionSet provCSet = buildProvConditionSet(clause);
537 List<Subject> clauseSubjects =
538 subjectMap.get(consCSet, provCSet);
539 if (clauseSubjects == null) {
540 clauseSubjects = new ArrayList<>();
541 subjectMap.put(consCSet, provCSet, clauseSubjects);
543 for (SubjectName sn : clause.getSubjectRefs()) {
544 Subject s = subjects.get(sn);
545 if (s != null) clauseSubjects.add(s);
550 policy.put(ckey, pkey,
551 resolvePolicy(match.contractTenant,
561 private List<ConsumerContractMatch> matchConsumerContracts(Tenant tenant,
562 EndpointGroup consumer) {
563 List<ConsumerContractMatch> matches = new ArrayList<>();
564 if (consumer.getConsumerNamedSelector() != null) {
565 for (ConsumerNamedSelector cns : consumer.getConsumerNamedSelector()) {
566 if (cns.getContract() == null) continue;
567 for (ContractId contractId : cns.getContract()) {
569 TenantUtils.findContract(tenant, contractId);
570 if (contract == null) continue;
571 matches.add(new ConsumerContractMatch(tenant, contract,
577 if (consumer.getConsumerTargetSelector() != null) {
578 for (ConsumerTargetSelector cts : consumer.getConsumerTargetSelector()) {
579 if (tenant.getContract() == null) continue;
580 for (Contract contract : tenant.getContract()) {
581 if (contract.getTarget() == null) continue;
582 for (Target t : contract.getTarget()) {
583 boolean match = true;
584 if (cts.getQualityMatcher() != null) {
585 for (QualityMatcher m : cts.getQualityMatcher()) {
586 if (!MatcherUtils.applyQualityMatcher(m, t)) {
593 matches.add(new ConsumerContractMatch(tenant,
603 // TODO match selectors also against contract references
604 // for (ConsumerTargetSelector cts : consumer.getConsumerTargetSelector()) {
605 // if (tenant.getContractRef() == null) continue;
606 // for (ContractRef c : tenant.getContractRef()) {
613 private void amendContractMatches(List<ContractMatch> matches,
614 List<ConsumerContractMatch> cMatches,
615 Tenant tenant, EndpointGroup provider,
616 ProviderSelectionRelator relator) {
617 if (cMatches == null) return;
618 for (ConsumerContractMatch cMatch : cMatches) {
619 matches.add(new ContractMatch(cMatch, tenant, provider, relator));
623 private List<ContractMatch>
624 matchProviderContracts(Tenant tenant, EndpointGroup provider,
627 List<ConsumerContractMatch>> consumerMatches) {
628 List<ContractMatch> matches = new ArrayList<>();
629 if (provider.getProviderNamedSelector() != null) {
630 for (ProviderNamedSelector pns : provider.getProviderNamedSelector()) {
631 if (pns.getContract() == null) continue;
632 for (ContractId contractId : pns.getContract()) {
633 Contract c = TenantUtils.findContract(tenant, contractId);
634 if (c == null) continue;
635 List<ConsumerContractMatch> cMatches =
636 consumerMatches.get(tenant.getId(), c.getId());
637 amendContractMatches(matches, cMatches, tenant, provider, pns);
641 if (provider.getProviderTargetSelector() != null) {
642 for (ProviderTargetSelector pts : provider.getProviderTargetSelector()) {
643 if (tenant.getContract() == null) continue;
644 for (Contract c : tenant.getContract()) {
645 if (c.getTarget() == null) continue;
646 for (Target t : c.getTarget()) {
647 boolean match = true;
648 if (pts.getQualityMatcher() != null) {
649 for (QualityMatcher m : pts.getQualityMatcher()) {
650 if (!MatcherUtils.applyQualityMatcher(m, t)) {
657 List<ConsumerContractMatch> cMatches =
658 consumerMatches.get(tenant.getId(),
660 amendContractMatches(matches, cMatches, tenant,
671 private static class TenantContext {
673 ListenerRegistration<DataChangeListener> registration;
675 AtomicReference<Tenant> tenant = new AtomicReference<Tenant>();
677 public TenantContext(TenantId tenantId,
678 ListenerRegistration<DataChangeListener> registration) {
680 //this.tenantId = tenantId;
681 this.registration = registration;
686 * Represents a selected contract made by endpoint groups matching it
687 * using selection relators. This is the result of the contract selection
693 protected static class ContractMatch extends ConsumerContractMatch {
695 * The tenant ID of the provider endpoint group
697 final Tenant providerTenant;
700 * The provider endpoint group
702 final EndpointGroup provider;
705 * The provider selection relator that was used to match the contract
707 final ProviderSelectionRelator providerRelator;
709 public ContractMatch(ConsumerContractMatch consumerMatch,
710 Tenant providerTenant, EndpointGroup provider,
711 ProviderSelectionRelator providerRelator) {
712 super(consumerMatch.contractTenant,
713 consumerMatch.contract,
714 consumerMatch.consumerTenant,
715 consumerMatch.consumer,
716 consumerMatch.consumerRelator);
717 this.providerTenant = providerTenant;
718 this.provider = provider;
719 this.providerRelator = providerRelator;
724 private static class ConsumerContractMatch {
726 * The tenant of the matching contract
728 final Tenant contractTenant;
731 * The matching contract
733 final Contract contract;
736 * The tenant for the endpoint group
738 final Tenant consumerTenant;
741 * The consumer endpoint group
743 final EndpointGroup consumer;
746 * The consumer selection relator that was used to match the contract
748 final ConsumerSelectionRelator consumerRelator;
751 public ConsumerContractMatch(Tenant contractTenant,
753 Tenant consumerTenant,
754 EndpointGroup consumer,
755 ConsumerSelectionRelator consumerRelator) {
757 this.contractTenant = contractTenant;
758 this.contract = contract;
759 this.consumerTenant = consumerTenant;
760 this.consumer = consumer;
761 this.consumerRelator = consumerRelator;
766 private class PolicyChangeListener implements DataChangeListener {
767 final TenantId tenantId;
769 public PolicyChangeListener(TenantId tenantId) {
771 this.tenantId = tenantId;
775 public void onDataChanged(AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> arg0) {
776 updateTenant(tenantId);