Feature uses features-parent as parent
[groupbasedpolicy.git] / renderers / opflex / src / main / java / org / opendaylight / groupbasedpolicy / renderer / opflex / Identity.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.renderer.opflex;
10
11 import java.util.ArrayList;
12 import java.util.Collections;
13 import java.util.List;
14 import java.util.Set;
15 import java.util.concurrent.ConcurrentHashMap;
16 import java.util.regex.Pattern;
17
18 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
19 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddressBuilder;
20 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2BridgeDomainId;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L3ContextId;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3Address;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3AddressBuilder;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3;
27
28 import com.google.common.net.InetAddresses;
29
30 /**
31  * An Identity for OpFlex. Identities can take on many
32  * forms, so it's possible that this class may be replaced
33  * by an abstract class with different concrete types.
34  * At the moment, we're only dealing with IP and MAC
35  * addresses.
36  * This class also provides methods for getting the identity
37  * in forms by the yang model, and are therefore usable by
38  * other classes in the policy model (e.g. the objects
39  * needed by the Endpoint Registry).
40  */
41 public class Identity {
42
43     enum IdentityType {
44         UNKNOWN, IP_ADDRESS, MAC_ADDRESS
45     }
46
47     private IdentityType type = IdentityType.UNKNOWN;
48     private L3ContextId l3Context = null;
49     private IpAddress primaryIp = null;
50     private Set<IpAddress> ips = null;
51     private L2BridgeDomainId l2Context = null;
52     private MacAddress mac = null;
53
54     public Identity(String id) {
55         /*
56          * Determine the ID type and populate
57          */
58         if (idIsIp(id)) {
59             type = IdentityType.IP_ADDRESS;
60             ips = Collections.newSetFromMap(new ConcurrentHashMap<IpAddress, Boolean>());
61             if (primaryIp == null)
62                 primaryIp = normalizeIpAddress(id);
63             ips.add(normalizeIpAddress(id));
64         } else if (idIsMac(id)) {
65             type = IdentityType.MAC_ADDRESS;
66             mac = normalizeMacAddress(id);
67         }
68
69     }
70
71     public Identity(Endpoint ep) {
72         type = IdentityType.MAC_ADDRESS;
73         mac = ep.getMacAddress();
74         l2Context = ep.getL2Context();
75     }
76
77     public Identity(EndpointL3 ep) {
78         type = IdentityType.IP_ADDRESS;
79         ips = Collections.newSetFromMap(new ConcurrentHashMap<IpAddress, Boolean>());
80         primaryIp = ep.getIpAddress();
81         List<L3Address> l3List = ep.getL3Address();
82         for (L3Address addr : l3List) {
83             ips.add(addr.getIpAddress());
84         }
85     }
86
87     public void setContext(String context) {
88         switch (type) {
89             case MAC_ADDRESS:
90                 l2Context = new L2BridgeDomainId(context);
91                 break;
92             case IP_ADDRESS:
93                 l3Context = new L3ContextId(context);
94                 break;
95             default:
96                 break;
97         }
98     }
99
100     /**
101      * Adds a new identifier to the list. Some types of
102      * identities allow for list of identifiers (e.g. L3).
103      *
104      * @param id The new identifier to add to the list
105      */
106     public void addId(String id) {
107         switch (type) {
108             case IP_ADDRESS:
109                 ips.add(normalizeIpAddress(id));
110                 break;
111             default:
112                 break;
113         }
114     }
115
116     private boolean idIsIp(String id) {
117         return InetAddresses.isInetAddress(id);
118     }
119
120     /*
121      * Verifies MAC addresses with the following formats:
122      * 0xAA:0xBB:0xCC:0xDD:0xEE:0xFF
123      * AA:BB:CC:DD:EE:FF
124      * 0xAA:BB:CC:DD:EE:FF
125      * 0xAA-0xBB-0xCC-0xDD-0xEE-0xFF
126      */
127     private boolean idIsMac(String id) {
128         /*
129          * First check/remove separators
130          */
131         String[] sixFields = id.split(":");
132         if (sixFields.length != 6) {
133             sixFields = id.split("-");
134             if (sixFields.length != 6) {
135                 return false;
136             }
137         }
138
139         for (String field : sixFields) {
140             /* Strip '0x' if present */
141             field = field.replace("0x", "");
142             if (field.length() > 2 || field.length() < 1) {
143                 return false;
144             }
145             if (!Pattern.matches("[0-9a-fA-F]{1,2}", field)) {
146                 return false;
147             }
148         }
149         return true;
150     }
151
152     /**
153      * Check if this {@link Identity} is an L3 type (Ip Address)
154      *
155      * @return true if L3, false if not
156      */
157     public boolean isL3() {
158         return (type == IdentityType.IP_ADDRESS);
159     }
160
161     /**
162      * Check if this {@link Identity} is an L2 type (MAC Address)
163      *
164      * @return true if L2, false if not
165      */
166     public boolean isL2() {
167         return (type == IdentityType.MAC_ADDRESS);
168     }
169
170     public boolean valid() {
171         switch (type) {
172             case MAC_ADDRESS:
173                 if (getL2Context() != null && mac != null) {
174                     return true;
175                 }
176                 break;
177             case IP_ADDRESS:
178                 if (getL3Context() != null && primaryIp != null) {
179                     return true;
180                 }
181             default:
182                 break;
183
184         }
185         return false;
186     }
187
188     /**
189      * Return the context, regardless of type, as a string.
190      *
191      * @return String representing the context for this Identity
192      */
193     public String contextAsString() {
194         switch (type) {
195             case MAC_ADDRESS:
196                 return l2Context.getValue();
197             case IP_ADDRESS:
198                 return l3Context.getValue();
199             default:
200                 return null;
201         }
202     }
203
204     /**
205      * Returns the identity as a string. The format
206      * of the string depends on the identity type.
207      * When the identity is a actually a list, only
208      * the first identity is returned.
209      *
210      * @return null if type is UKNOWN, otherwise String
211      */
212     public String identityAsString() {
213         switch (type) {
214             case MAC_ADDRESS:
215                 return mac.getValue();
216             case IP_ADDRESS:
217                 List<IpAddress> ipl = new ArrayList<IpAddress>(ips);
218                 IpAddress i = ipl.get(0);
219                 if (i.getIpv4Address() != null) {
220                     return i.getIpv4Address().getValue();
221                 } else if (i.getIpv6Address() != null) {
222                     return i.getIpv6Address().getValue();
223                 }
224             default:
225         }
226         return null;
227     }
228
229     /**
230      * Get the L2 context in an Endpoint Registry
231      * compatible format
232      *
233      * @return The Layer 2 context
234      */
235     public L2BridgeDomainId getL2Context() {
236         return l2Context;
237     }
238
239     /**
240      * Get the L2 identity in an Endpoint Registry
241      * compatible format
242      *
243      * @return The Layer 2 identity
244      */
245     public MacAddress getL2Identity() {
246         return mac;
247     }
248
249     /**
250      * Get the L3 context in an Endpoint Registry
251      * compatible format
252      *
253      * @return The Layer 3 context
254      */
255     public L3ContextId getL3Context() {
256         return l3Context;
257     }
258
259     /**
260      * Get the L3 identity in an Endpoint Registry
261      * compatible format
262      *
263      * @return The Layer 3 identity
264      */
265     public IpAddress getL3Identity() {
266         return primaryIp;
267     }
268
269     public List<L3Address> getL3Addresses() {
270
271         List<L3Address> l3List = new ArrayList<L3Address>();
272         List<IpAddress> ipList = new ArrayList<IpAddress>();
273         ipList.addAll(ips);
274         for (IpAddress i : ipList) {
275             L3AddressBuilder l3ab = new L3AddressBuilder();
276             l3ab.setIpAddress(i);
277             l3ab.setL3Context(l3Context);
278             l3List.add(l3ab.build());
279         }
280
281         return l3List;
282     }
283
284     private IpAddress normalizeIpAddress(String identifier) {
285         return IpAddressBuilder.getDefaultInstance(identifier);
286     }
287
288     private MacAddress normalizeMacAddress(String identifier) {
289         MacAddress m = new MacAddress(identifier);
290         return m;
291     }
292
293     @Override
294     public int hashCode() {
295         final int prime = 31;
296         int result = 1;
297         result = prime * result + ((ips == null) ? 0 : ips.hashCode());
298         result = prime * result + ((l2Context == null) ? 0 : l2Context.hashCode());
299         result = prime * result + ((l3Context == null) ? 0 : l3Context.hashCode());
300         result = prime * result + ((mac == null) ? 0 : mac.hashCode());
301         result = prime * result + ((primaryIp == null) ? 0 : primaryIp.hashCode());
302         result = prime * result + ((type == null) ? 0 : type.hashCode());
303         return result;
304     }
305
306     @Override
307     public boolean equals(Object obj) {
308         if (this == obj)
309             return true;
310         if (obj == null)
311             return false;
312         if (getClass() != obj.getClass())
313             return false;
314         Identity other = (Identity) obj;
315         if (ips == null) {
316             if (other.ips != null)
317                 return false;
318         } else if (!ips.equals(other.ips))
319             return false;
320         if (l2Context == null) {
321             if (other.l2Context != null)
322                 return false;
323         } else if (!l2Context.equals(other.l2Context))
324             return false;
325         if (l3Context == null) {
326             if (other.l3Context != null)
327                 return false;
328         } else if (!l3Context.equals(other.l3Context))
329             return false;
330         if (mac == null) {
331             if (other.mac != null)
332                 return false;
333         } else if (!mac.equals(other.mac))
334             return false;
335         if (primaryIp == null) {
336             if (other.primaryIp != null)
337                 return false;
338         } else if (!primaryIp.equals(other.primaryIp))
339             return false;
340         if (type != other.type)
341             return false;
342         return true;
343     }
344
345 }