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