Fixed NAT in OFOverlay based on EIG
[groupbasedpolicy.git] / groupbasedpolicy / src / main / java / org / opendaylight / groupbasedpolicy / dto / IndexedTenant.java
1 /*
2  * Copyright (c) 2014 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.dto;
10
11 import java.util.Collection;
12 import java.util.Collections;
13 import java.util.HashMap;
14 import java.util.HashSet;
15 import java.util.Map;
16 import java.util.Set;
17
18 import javax.annotation.concurrent.Immutable;
19
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ActionName;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ClassifierName;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContractId;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.NetworkDomainId;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.SubnetId;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.NetworkDomain;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.Tenant;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.ForwardingContext;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.Policy;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2BridgeDomain;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2FloodDomain;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L3Context;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.Subnet;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.Contract;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.EndpointGroup;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.ExternalImplicitGroup;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.SubjectFeatureInstances;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.subject.feature.instances.ActionInstance;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.subject.feature.instances.ClassifierInstance;
40
41 import com.google.common.base.Function;
42 import com.google.common.collect.Collections2;
43 import com.google.common.collect.ImmutableSet;
44
45 /**
46  * Wrap some convenient indexes around a {@link Tenant} object
47  * @author readams
48  */
49 @Immutable
50 public class IndexedTenant {
51     private final Tenant tenant;
52     private final int hashCode;
53
54     private final Map<EndpointGroupId, EndpointGroup> endpointGroups =
55             new HashMap<>();
56     private final Map<ContractId, Contract> contracts =
57             new HashMap<>();
58     private final Map<String, NetworkDomain> networkDomains =
59             new HashMap<>();
60     private final Map<ClassifierName, ClassifierInstance> classifiers =
61             new HashMap<>();
62     private final Map<ActionName, ActionInstance> actions =
63             new HashMap<>();
64     private final Map<String, Set<SubnetId>> subnetMap = new HashMap<>();
65     private Set<ExternalImplicitGroup> externalImplicitGroups = Collections.emptySet();
66
67     public IndexedTenant(Tenant tenant) {
68         this.tenant = tenant;
69         this.hashCode = tenant.hashCode();
70         if (tenant.getPolicy() != null) {
71             processPolicy(tenant.getPolicy());
72         }
73         if (tenant.getForwardingContext() != null) {
74             processForwardingContext(tenant.getForwardingContext());
75         }
76     }
77
78     private void processPolicy(Policy policy) {
79         if (policy.getEndpointGroup() != null) {
80             for (EndpointGroup eg : policy.getEndpointGroup()) {
81                 endpointGroups.put(eg.getId(), eg);
82             }
83         }
84         if (policy.getExternalImplicitGroup() != null) {
85             externalImplicitGroups = ImmutableSet.copyOf(policy.getExternalImplicitGroup());
86         }
87         if (policy.getContract() != null) {
88             for (Contract c : policy.getContract()) {
89                 contracts.put(c.getId(), c);
90             }
91         }
92         if (policy.getSubjectFeatureInstances() != null) {
93             SubjectFeatureInstances sfi = policy.getSubjectFeatureInstances();
94             if (sfi.getClassifierInstance() != null) {
95                 for (ClassifierInstance ci : sfi.getClassifierInstance()) {
96                     classifiers.put(ci.getName(), ci);
97                 }
98             }
99             if (sfi.getActionInstance() != null) {
100                 for (ActionInstance action : sfi.getActionInstance()) {
101                     actions.put(action.getName(), action);
102                 }
103             }
104         }
105     }
106
107     private void processForwardingContext(ForwardingContext fwCtx) {
108         if (fwCtx.getL3Context() != null) {
109             for (L3Context c : fwCtx.getL3Context()) {
110                 networkDomains.put(c.getId().getValue(), c);
111             }
112         }
113         if (fwCtx.getL2BridgeDomain() != null) {
114             for (L2BridgeDomain c : fwCtx.getL2BridgeDomain()) {
115                 networkDomains.put(c.getId().getValue(), c);
116             }
117         }
118         if (fwCtx.getL2FloodDomain() != null) {
119             for (L2FloodDomain c : fwCtx.getL2FloodDomain()) {
120                 networkDomains.put(c.getId().getValue(), c);
121             }
122         }
123         if (fwCtx.getSubnet() != null) {
124             for (Subnet s : fwCtx.getSubnet()) {
125                 networkDomains.put(s.getId().getValue(), s);
126                 Set<SubnetId> sset = subnetMap.get(s.getParent().getValue());
127                 if (sset == null) {
128                     subnetMap.put(s.getParent().getValue(), sset = new HashSet<SubnetId>());
129                 }
130                 sset.add(s.getId());
131             }
132         }
133     }
134
135     /**
136      * Get the underlying tenant object
137      * @return the {@link Tenant}
138      */
139     public Tenant getTenant() {
140         return tenant;
141     }
142
143     /**
144      * Gets all external implicit groups in the tenant
145      * @return immutable set of EIGs
146      */
147     public Set<ExternalImplicitGroup> getExternalImplicitGroups() {
148         return externalImplicitGroups;
149     }
150     
151     /**
152      * Look up the network domain specified
153      * @param id the {@link NetworkDomainId}
154      * @return the {@link NetworkDomain} if it exists, or <code>null</code> 
155      * otherwise
156      */
157     public NetworkDomain getNetworkDomain(NetworkDomainId id) {
158         return networkDomains.get(id.getValue());
159     }
160
161     /**
162      * Look up the endpoint group specified
163      * @param id the {@link EndpointGroupId}
164      * @return the {@link EndpointGroup} if it exists, or <code>null</code> 
165      * otherwise
166      */
167     public EndpointGroup getEndpointGroup(EndpointGroupId id) {
168         return endpointGroups.get(id);
169     }
170     
171     /**
172      * Look up the contract specified
173      * @param id the {@link ContractId}
174      * @return the {@link Contract} if it exists, or <code>null</code> 
175      * otherwise
176      */
177     public Contract getContract(ContractId id) {
178         return contracts.get(id);
179     }
180     
181     /**
182      * Look up the classifier instance specified
183      * @param name the {@link ClassifierName}
184      * @return the {@link ClassifierInstance} if it exists, or <code>null</code> 
185      * otherwise
186      */
187     public ClassifierInstance getClassifier(ClassifierName name) {
188         return classifiers.get(name);
189     }
190
191     /**
192      * Look up the classifier instance specified
193      * @param name the {@link ActionName}
194      * @return the {@link ActionInstance} if it exists, or <code>null</code> 
195      * otherwise
196      */
197     public ActionInstance getAction(ActionName name) {
198         return actions.get(name);
199     }
200
201     /**
202      * Get the layer 3 context for the specified network domain by walking
203      * up the hierarchy
204      * @param id the {@link NetworkDomainId} for the network domain
205      * @return the {@link L3Context} or <code>null</code> if it does not exist
206      */
207     public L3Context resolveL3Context(NetworkDomainId id) {
208         return resolveDomain(L3Context.class, id);
209     }
210
211     /**
212      * Get the layer 2 bridge domain for the specified network domain by walking
213      * up the hierarchy
214      * @param id the {@link NetworkDomainId} for the network domain
215      * @return the {@link L2BridgeDomain} or <code>null</code> if it does
216      * not exist
217      */
218     public L2BridgeDomain resolveL2BridgeDomain(NetworkDomainId id) {
219         return resolveDomain(L2BridgeDomain.class, id);
220     }
221
222     /**
223      * Get the layer 2 flood domain for the specified network domain by walking
224      * up the hierarchy
225      * @param id the {@link NetworkDomainId} for the network domain
226      * @return the {@link L2FloodDomain} or <code>null</code> if it does
227      * not exist
228      */
229     public L2FloodDomain resolveL2FloodDomain(NetworkDomainId id) {
230         return resolveDomain(L2FloodDomain.class, id);
231     }
232
233     /**
234      * Resolve all subnets applicable to the given network domain ID
235      * @param id the {@link NetworkDomainId}
236      * @return the set of subnets.  Cannot be null, but could be empty.
237      */
238     public Collection<Subnet> resolveSubnets(NetworkDomainId id) {
239         Set<SubnetId> sset = new HashSet<>();
240         HashSet<NetworkDomainId> visited = new HashSet<>();        
241         while (id != null) {
242             if (visited.contains(id)) break;
243             visited.add(id);
244             Set<SubnetId> cursset = subnetMap.get(id.getValue());
245             if (cursset != null)
246                 sset.addAll(cursset);
247             NetworkDomain d = networkDomains.get(id.getValue());
248             if (d == null) break;
249             if (d instanceof Subnet) {
250                 id = ((Subnet)d).getParent();
251                 sset.add(((Subnet) d).getId());
252             } 
253             else if (d instanceof L2BridgeDomain)
254                 id = ((L2BridgeDomain)d).getParent();
255             else if (d instanceof L2FloodDomain)
256                 id = ((L2FloodDomain)d).getParent();
257             else
258                 id = null;
259         }
260         return Collections2.transform(sset, new Function<SubnetId, Subnet>() {
261             @Override
262             public Subnet apply(SubnetId input) {
263                 return (Subnet)networkDomains.get(input.getValue());
264             }
265         });
266     }
267
268     // ******
269     // Object
270     // ******
271     
272     @Override
273     public int hashCode() {
274         return hashCode;
275     }
276
277     @Override
278     public boolean equals(Object obj) {
279         if (this == obj)
280             return true;
281         if (obj == null)
282             return false;
283         if (getClass() != obj.getClass())
284             return false;
285         IndexedTenant other = (IndexedTenant) obj;
286         if (tenant == null) {
287             if (other.tenant != null)
288                 return false;
289         } else if (!tenant.equals(other.tenant))
290             return false;
291         return true;
292     }
293
294     // **************
295     // Implementation
296     // **************
297
298     private <C extends NetworkDomain> C resolveDomain(Class<C> domainClass,
299                                                       NetworkDomainId id) {
300         HashSet<NetworkDomainId> visited = new HashSet<>();        
301         while (id != null) {
302             if (visited.contains(id)) return null;
303             visited.add(id);
304             NetworkDomain d = networkDomains.get(id.getValue());
305             if (d == null) return null;
306             if (domainClass.isInstance(d)) return domainClass.cast(d);
307             if (d instanceof Subnet)
308                 id = ((Subnet)d).getParent();
309             else if (d instanceof L2BridgeDomain)
310                 id = ((L2BridgeDomain)d).getParent();
311             else if (d instanceof L2FloodDomain)
312                 id = ((L2FloodDomain)d).getParent();
313             else
314                 id = null;
315         }
316         return null;
317     }
318 }