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