L3: Add eth to br-ex
[ovsdb.git] / openstack / net-virt / src / main / java / org / opendaylight / ovsdb / openstack / netvirt / translator / NeutronSubnetIPAllocationPool.java
1 /*
2  * Copyright (c) 2013, 2015 IBM Corporation 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.ovsdb.openstack.netvirt.translator;
10
11 import java.io.Serializable;
12 import java.math.BigInteger;
13 import java.net.InetAddress;
14 import java.net.Inet6Address;
15 import java.util.ArrayList;
16 import java.util.List;
17
18 import javax.xml.bind.annotation.XmlAccessType;
19 import javax.xml.bind.annotation.XmlAccessorType;
20 import javax.xml.bind.annotation.XmlElement;
21 import javax.xml.bind.annotation.XmlRootElement;
22
23 import org.slf4j.Logger;
24 import org.slf4j.LoggerFactory;
25
26 @XmlRootElement
27 @XmlAccessorType(XmlAccessType.NONE)
28 public class NeutronSubnetIPAllocationPool implements Serializable {
29     private static final Logger LOGGER = LoggerFactory
30             .getLogger(NeutronSubnetIPAllocationPool.class);
31
32     private static final long serialVersionUID = 1L;
33
34     private static final int BYTE_LENGTH = 8;
35     private static final int IPV4_DOTTED_QUADS = 4;
36     private static final int IPV4_DOTTED_QUAD_OFFSET = 3;
37     private static final int IPV4_DOTTED_QUAD_MASK = 255;
38
39     // See OpenStack Network API v2.0 Reference for description of
40     // annotated attributes
41
42     @XmlElement(name = "start")
43     String poolStart;
44
45     @XmlElement(name = "end")
46     String poolEnd;
47
48     public NeutronSubnetIPAllocationPool() {
49     }
50
51     public NeutronSubnetIPAllocationPool(String lowAddress, String highAddress) {
52         poolStart = lowAddress;
53         poolEnd = highAddress;
54     }
55
56     public String getPoolStart() {
57         return poolStart;
58     }
59
60     public void setPoolStart(String poolStart) {
61         this.poolStart = poolStart;
62     }
63
64     public String getPoolEnd() {
65         return poolEnd;
66     }
67
68     public void setPoolEnd(String poolEnd) {
69         this.poolEnd = poolEnd;
70     }
71
72     /**
73      * This method determines if this allocation pool contains the
74      * input IPv4 address
75      *
76      * @param inputString
77      *            IPv4 address in dotted decimal format
78      * @return a boolean on whether the pool contains the address or not
79      */
80
81     public boolean contains(String inputString) {
82         long inputIP = convert(inputString);
83         long startIP = convert(poolStart);
84         long endIP = convert(poolEnd);
85         return (inputIP >= startIP && inputIP <= endIP);
86     }
87
88     /**
89      * This static method converts the supplied IPv4 address to a long
90      * integer for comparison
91      *
92      * @param inputString
93      *            IPv4 address in dotted decimal format
94      * @return high-endian representation of the IPv4 address as a long.
95      *          This method will return 0 if the input is null.
96      */
97
98     static long convert(String inputString) {
99         long ans = 0;
100         if (inputString != null) {
101             String[] parts = inputString.split("\\.");
102             for (String part: parts) {
103                 ans <<= BYTE_LENGTH;
104                 ans |= Integer.parseInt(part);
105             }
106         }
107         return ans;
108     }
109
110     /**
111      * This method determines if this allocation pool contains the
112      * input IPv4 address
113      *
114      * @param inputString
115      *            IPv4 address in dotted decimal format
116      * @return a boolean on whether the pool contains the address or not
117      */
118
119     public boolean containsV6(String inputString) {
120         BigInteger inputIP = convertV6(inputString);
121         BigInteger startIP = convertV6(poolStart);
122         BigInteger endIP = convertV6(poolEnd);
123         return (inputIP.compareTo(startIP) >= 0 && inputIP.compareTo(endIP) <= 0);
124     }
125
126     /**
127      * This static method converts the supplied IPv4 address to a long
128      * integer for comparison
129      *
130      * @param inputString
131      *            IPv6 address in dotted decimal format
132      * @return high-endian representation of the IPv4 address as a BigInteger.
133      *          This method will return 0 if the input is null.
134      */
135
136     static BigInteger convertV6(String inputString) {
137         if (inputString == null) {
138             return BigInteger.ZERO;
139         }
140         try {
141             return new BigInteger(((Inet6Address) InetAddress.getByName(inputString)).getAddress());
142         } catch (Exception e) {
143             LOGGER.error("convertV6 error", e);
144             return BigInteger.ZERO;
145         }
146     }
147
148     /**
149      * This static method converts the supplied high-ending long back
150      * into a dotted decimal representation of an IPv4 address
151      *
152      * @param l
153      *            high-endian representation of the IPv4 address as a long
154      * @return IPv4 address in dotted decimal format
155      */
156     static String longToIP(long input) {
157         int part;
158         long ipLong = input;
159         String[] parts = new String[IPV4_DOTTED_QUADS];
160         for (part = 0; part < IPV4_DOTTED_QUADS; part++) {
161             parts[IPV4_DOTTED_QUAD_OFFSET-part] = String.valueOf(ipLong & IPV4_DOTTED_QUAD_MASK);
162             ipLong >>= BYTE_LENGTH;
163         }
164         return join(parts,".");
165     }
166
167     /**
168      * This static method converts the supplied high-ending long back
169      * into a dotted decimal representation of an IPv4 address
170      *
171      * @param l
172      *            high-endian representation of the IPv4 address as a long
173      * @return IPv4 address in dotted decimal format
174      */
175     static String bigIntegerToIP(BigInteger b) {
176         try {
177             return Inet6Address.getByAddress(b.toByteArray()).getHostAddress();
178         } catch (Exception e) {
179             LOGGER.error("bigIntegerToIP", e);
180             return "ERROR";
181         }
182     }
183
184     /*
185      * helper routine used by longToIP
186      */
187     public static String join(String r[],String separator)
188     {
189         if (r.length == 0) {
190             return "";
191         }
192         StringBuilder sb = new StringBuilder();
193         int i;
194         for(i = 0;i < r.length - 1;i++) {
195             sb.append(r[i]);
196             sb.append(separator);
197         }
198         return sb.toString() + r[i];
199     }
200
201     /*
202      * This method splits the current instance by removing the supplied
203      * parameter.
204      *
205      * If the parameter is either the low or high address,
206      * then that member is adjusted and a list containing just this instance
207      * is returned.
208      *
209      * If the parameter is in the middle of the pool, then
210      * create two new instances, one ranging from low to parameter-1
211      * the other ranging from parameter+1 to high
212      */
213     public List<NeutronSubnetIPAllocationPool> splitPool(String ipAddress) {
214         List<NeutronSubnetIPAllocationPool> ans = new ArrayList<NeutronSubnetIPAllocationPool>();
215         long gIP = NeutronSubnetIPAllocationPool.convert(ipAddress);
216         long sIP = NeutronSubnetIPAllocationPool.convert(poolStart);
217         long eIP = NeutronSubnetIPAllocationPool.convert(poolEnd);
218         long i;
219         NeutronSubnetIPAllocationPool p = new NeutronSubnetIPAllocationPool();
220         boolean poolStarted = false;
221         for (i = sIP; i <= eIP; i++) {
222             if (i == sIP) {
223                 if (i != gIP) {
224                     p.setPoolStart(poolStart);
225                     poolStarted = true;
226                 } else {
227                     //FIX for bug 533
228                     p.setPoolStart(NeutronSubnetIPAllocationPool.longToIP(i+1));
229                 }
230             }
231             if (i == eIP) {
232                 if (i != gIP) {
233                     p.setPoolEnd(poolEnd);
234                 } else {
235                     p.setPoolEnd(NeutronSubnetIPAllocationPool.longToIP(i-1));
236                 }
237                 ans.add(p);
238             }
239             if (i != sIP && i != eIP) {
240                 if (i != gIP) {
241                     if (!poolStarted) {
242                         p.setPoolStart(NeutronSubnetIPAllocationPool.longToIP(i));
243                         poolStarted = true;
244                     }
245                 } else {
246                     p.setPoolEnd(NeutronSubnetIPAllocationPool.longToIP(i-1));
247                     poolStarted = false;
248                     ans.add(p);
249                     p = new NeutronSubnetIPAllocationPool();
250                     // Fix for 2120
251                     p.setPoolStart(NeutronSubnetIPAllocationPool.longToIP(i+1));
252                     poolStarted = true;
253                 }
254             }
255         }
256         return ans;
257     }
258
259     @Override
260     public String toString() {
261         return "NeutronSubnetIPAllocationPool [" +
262             "start=" + poolStart +
263             ", end=" + poolEnd + "]";
264     }
265
266     /*
267      * This method splits the current instance by removing the supplied
268      * parameter.
269      *
270      * If the parameter is either the low or high address,
271      * then that member is adjusted and a list containing just this instance
272      * is returned.
273      new *
274      * If the parameter is in the middle of the pool, then
275      * create two new instances, one ranging from low to parameter-1
276      * the other ranging from parameter+1 to high
277      * If the pool is a single address, return null
278      */
279     public List<NeutronSubnetIPAllocationPool> splitPoolV6(String ipAddress) {
280         List<NeutronSubnetIPAllocationPool> ans = new ArrayList<NeutronSubnetIPAllocationPool>();
281         BigInteger gIP = NeutronSubnetIPAllocationPool.convertV6(ipAddress);
282         BigInteger sIP = NeutronSubnetIPAllocationPool.convertV6(poolStart);
283         BigInteger eIP = NeutronSubnetIPAllocationPool.convertV6(poolEnd);
284         if (gIP.compareTo(sIP) == 0 && gIP.compareTo(eIP) < 0) {
285             NeutronSubnetIPAllocationPool p = new NeutronSubnetIPAllocationPool();
286             p.setPoolStart(NeutronSubnetIPAllocationPool.bigIntegerToIP(sIP.add(BigInteger.ONE)));
287             p.setPoolEnd(poolEnd);
288             ans.add(p);
289             return(ans);
290         }
291         if (gIP.compareTo(eIP) == 0 && gIP.compareTo(sIP) > 0) {
292             NeutronSubnetIPAllocationPool p = new NeutronSubnetIPAllocationPool();
293             p.setPoolStart(poolStart);
294             p.setPoolEnd(NeutronSubnetIPAllocationPool.bigIntegerToIP(eIP.subtract(BigInteger.ONE)));
295             ans.add(p);
296             return(ans);
297         }
298         if (gIP.compareTo(eIP) < 0 && gIP.compareTo(sIP) > 0) {
299             NeutronSubnetIPAllocationPool p = new NeutronSubnetIPAllocationPool();
300             p.setPoolStart(poolStart);
301             p.setPoolEnd(NeutronSubnetIPAllocationPool.bigIntegerToIP(gIP.subtract(BigInteger.ONE)));
302             ans.add(p);
303             NeutronSubnetIPAllocationPool p2 = new NeutronSubnetIPAllocationPool();
304             p2.setPoolStart(NeutronSubnetIPAllocationPool.bigIntegerToIP(gIP.add(BigInteger.ONE)));
305             p2.setPoolEnd(poolEnd);
306             ans.add(p2);
307             return ans;
308         }
309         return null;
310     }
311 }