8b1a8d6af4bb50c13e8b2166bac245fe7d41f0ce
[controller.git] / opendaylight / networkconfiguration / neutron / src / main / java / org / opendaylight / controller / networkconfig / neutron / NeutronSubnet.java
1 /*\r
2  * Copyright IBM Corporation, 2013.  All rights reserved.\r
3  *\r
4  * This program and the accompanying materials are made available under the\r
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
6  * and is available at http://www.eclipse.org/legal/epl-v10.html\r
7  */\r
8 \r
9 package org.opendaylight.controller.networkconfig.neutron;\r
10 \r
11 import java.util.ArrayList;\r
12 import java.util.Iterator;\r
13 import java.util.List;\r
14 import javax.xml.bind.annotation.XmlAccessType;\r
15 import javax.xml.bind.annotation.XmlAccessorType;\r
16 import javax.xml.bind.annotation.XmlElement;\r
17 import javax.xml.bind.annotation.XmlRootElement;\r
18 \r
19 import org.apache.commons.net.util.SubnetUtils;\r
20 import org.apache.commons.net.util.SubnetUtils.SubnetInfo;\r
21 \r
22 @XmlRootElement\r
23 @XmlAccessorType(XmlAccessType.NONE)\r
24 \r
25 public class NeutronSubnet {\r
26     // See OpenStack Network API v2.0 Reference for description of\r
27     // annotated attributes\r
28 \r
29     @XmlElement (name="id")\r
30     String subnetUUID;\r
31 \r
32     @XmlElement (name="network_id")\r
33     String networkUUID;\r
34 \r
35     @XmlElement (name="name")\r
36     String name;\r
37 \r
38     @XmlElement (defaultValue="4", name="ip_version")\r
39     Integer ipVersion;\r
40 \r
41     @XmlElement (name="cidr")\r
42     String cidr;\r
43 \r
44     @XmlElement (name="gateway_ip")\r
45     String gatewayIP;\r
46 \r
47     @XmlElement (name="dns_nameservers")\r
48     List<String> dnsNameservers;\r
49 \r
50     @XmlElement (name="allocation_pools")\r
51     List<NeutronSubnet_IPAllocationPool> allocationPools;\r
52 \r
53     @XmlElement (name="host_routes")\r
54     List<NeutronSubnet_HostRoute> hostRoutes;\r
55 \r
56     @XmlElement (defaultValue="true", name="enable_dhcp")\r
57     Boolean enableDHCP;\r
58 \r
59     @XmlElement (name="tenant_id")\r
60     String tenantID;\r
61 \r
62     /* stores the OpenStackPorts associated with an instance\r
63      * used to determine if that instance can be deleted.\r
64      */\r
65     List<NeutronPort> myPorts;\r
66 \r
67     boolean gatewayIPAssigned;\r
68 \r
69     public NeutronSubnet() {\r
70         myPorts = new ArrayList<NeutronPort>();\r
71     }\r
72 \r
73     public String getID() { return subnetUUID; }\r
74 \r
75     public String getSubnetUUID() {\r
76         return subnetUUID;\r
77     }\r
78 \r
79     public void setSubnetUUID(String subnetUUID) {\r
80         this.subnetUUID = subnetUUID;\r
81     }\r
82 \r
83     public String getNetworkUUID() {\r
84         return networkUUID;\r
85     }\r
86 \r
87     public void setNetworkUUID(String networkUUID) {\r
88         this.networkUUID = networkUUID;\r
89     }\r
90 \r
91     public String getName() {\r
92         return name;\r
93     }\r
94 \r
95     public void setName(String name) {\r
96         this.name = name;\r
97     }\r
98 \r
99     public Integer getIpVersion() {\r
100         return ipVersion;\r
101     }\r
102 \r
103     public void setIpVersion(Integer ipVersion) {\r
104         this.ipVersion = ipVersion;\r
105     }\r
106 \r
107     public String getCidr() {\r
108         return cidr;\r
109     }\r
110 \r
111     public void setCidr(String cidr) {\r
112         this.cidr = cidr;\r
113     }\r
114 \r
115     public String getGatewayIP() {\r
116         return gatewayIP;\r
117     }\r
118 \r
119     public void setGatewayIP(String gatewayIP) {\r
120         this.gatewayIP = gatewayIP;\r
121     }\r
122 \r
123     public List<String> getDnsNameservers() {\r
124         return dnsNameservers;\r
125     }\r
126 \r
127     public void setDnsNameservers(List<String> dnsNameservers) {\r
128         this.dnsNameservers = dnsNameservers;\r
129     }\r
130 \r
131     public List<NeutronSubnet_IPAllocationPool> getAllocationPools() {\r
132         return allocationPools;\r
133     }\r
134 \r
135     public void setAllocationPools(List<NeutronSubnet_IPAllocationPool> allocationPools) {\r
136         this.allocationPools = allocationPools;\r
137     }\r
138 \r
139     public List<NeutronSubnet_HostRoute> getHostRoutes() {\r
140         return hostRoutes;\r
141     }\r
142 \r
143     public void setHostRoutes(List<NeutronSubnet_HostRoute> hostRoutes) {\r
144         this.hostRoutes = hostRoutes;\r
145     }\r
146 \r
147     public boolean isEnableDHCP() {\r
148         if (enableDHCP == null) {\r
149             return true;\r
150         }\r
151         return enableDHCP;\r
152     }\r
153 \r
154     public Boolean getEnableDHCP() { return enableDHCP; }\r
155 \r
156     public void setEnableDHCP(Boolean newValue) {\r
157             enableDHCP = newValue;\r
158     }\r
159 \r
160     public String getTenantID() {\r
161         return tenantID;\r
162     }\r
163 \r
164     public void setTenantID(String tenantID) {\r
165         this.tenantID = tenantID;\r
166     }\r
167 \r
168     /**\r
169      * This method copies selected fields from the object and returns them\r
170      * as a new object, suitable for marshaling.\r
171      *\r
172      * @param fields\r
173      *            List of attributes to be extracted\r
174      * @return an OpenStackSubnets object with only the selected fields\r
175      * populated\r
176      */\r
177 \r
178     public NeutronSubnet extractFields(List<String> fields) {\r
179         NeutronSubnet ans = new NeutronSubnet();\r
180         Iterator<String> i = fields.iterator();\r
181         while (i.hasNext()) {\r
182             String s = i.next();\r
183             if (s.equals("id")) {\r
184                 ans.setSubnetUUID(this.getSubnetUUID());\r
185             }\r
186             if (s.equals("network_id")) {\r
187                 ans.setNetworkUUID(this.getNetworkUUID());\r
188             }\r
189             if (s.equals("name")) {\r
190                 ans.setName(this.getName());\r
191             }\r
192             if (s.equals("ip_version")) {\r
193                 ans.setIpVersion(this.getIpVersion());\r
194             }\r
195             if (s.equals("cidr")) {\r
196                 ans.setCidr(this.getCidr());\r
197             }\r
198             if (s.equals("gateway_ip")) {\r
199                 ans.setGatewayIP(this.getGatewayIP());\r
200             }\r
201             if (s.equals("dns_nameservers")) {\r
202                 List<String> nsList = new ArrayList<String>();\r
203                 nsList.addAll(this.getDnsNameservers());\r
204                 ans.setDnsNameservers(nsList);\r
205             }\r
206             if (s.equals("allocation_pools")) {\r
207                 List<NeutronSubnet_IPAllocationPool> aPools = new ArrayList<NeutronSubnet_IPAllocationPool>();\r
208                 aPools.addAll(this.getAllocationPools());\r
209                 ans.setAllocationPools(aPools);\r
210             }\r
211             if (s.equals("host_routes")) {\r
212                 List<NeutronSubnet_HostRoute> hRoutes = new ArrayList<NeutronSubnet_HostRoute>();\r
213                 hRoutes.addAll(this.getHostRoutes());\r
214                 ans.setHostRoutes(hRoutes);\r
215             }\r
216             if (s.equals("enable_dhcp")) {\r
217                 ans.setEnableDHCP(this.getEnableDHCP());\r
218             }\r
219             if (s.equals("tenant_id")) {\r
220                 ans.setTenantID(this.getTenantID());\r
221             }\r
222         }\r
223         return ans;\r
224     }\r
225 \r
226     /* test to see if the cidr address used to define this subnet\r
227      * is a valid network address (an necessary condition when creating\r
228      * a new subnet)\r
229      */\r
230     public boolean isValidCIDR() {\r
231         try {\r
232             SubnetUtils util = new SubnetUtils(cidr);\r
233             SubnetInfo info = util.getInfo();\r
234             if (!info.getNetworkAddress().equals(info.getAddress())) {\r
235                 return false;\r
236             }\r
237         } catch (Exception e) {\r
238             return false;\r
239         }\r
240         return true;\r
241     }\r
242 \r
243     /* test to see if the gateway IP specified overlaps with specified\r
244      * allocation pools (an error condition when creating a new subnet\r
245      * or assigning a gateway IP)\r
246      */\r
247     public boolean gatewayIP_Pool_overlap() {\r
248         Iterator<NeutronSubnet_IPAllocationPool> i = allocationPools.iterator();\r
249         while (i.hasNext()) {\r
250             NeutronSubnet_IPAllocationPool pool = i.next();\r
251             if (pool.contains(gatewayIP)) {\r
252                 return true;\r
253             }\r
254         }\r
255         return false;\r
256     }\r
257 \r
258     public boolean initDefaults() {\r
259         if (enableDHCP == null) {\r
260             enableDHCP = true;\r
261         }\r
262         if (ipVersion == null) {\r
263             ipVersion = 4;\r
264         }\r
265         gatewayIPAssigned = false;\r
266         dnsNameservers = new ArrayList<String>();\r
267         allocationPools = new ArrayList<NeutronSubnet_IPAllocationPool>();\r
268         hostRoutes = new ArrayList<NeutronSubnet_HostRoute>();\r
269         try {\r
270             SubnetUtils util = new SubnetUtils(cidr);\r
271             SubnetInfo info = util.getInfo();\r
272             if (gatewayIP == null) {\r
273                 gatewayIP = info.getLowAddress();\r
274             }\r
275             if (allocationPools.size() < 1) {\r
276                 NeutronSubnet_IPAllocationPool source =\r
277                     new NeutronSubnet_IPAllocationPool(info.getLowAddress(),\r
278                             info.getHighAddress());\r
279                 allocationPools = source.splitPool(gatewayIP);\r
280             }\r
281         } catch (Exception e) {\r
282             return false;\r
283         }\r
284         return true;\r
285     }\r
286 \r
287     public List<NeutronPort> getPortsInSubnet() {\r
288         return myPorts;\r
289     }\r
290 \r
291     public void addPort(NeutronPort port) {\r
292         myPorts.add(port);\r
293     }\r
294 \r
295     public void removePort(NeutronPort port) {\r
296         myPorts.remove(port);\r
297     }\r
298 \r
299     /* this method tests to see if the supplied IPv4 address\r
300      * is valid for this subnet or not\r
301      */\r
302     public boolean isValidIP(String ipAddress) {\r
303         try {\r
304             SubnetUtils util = new SubnetUtils(cidr);\r
305             SubnetInfo info = util.getInfo();\r
306             return info.isInRange(ipAddress);\r
307         } catch (Exception e) {\r
308             return false;\r
309         }\r
310     }\r
311 \r
312     /* test to see if the supplied IPv4 address is part of one of the\r
313      * available allocation pools or not\r
314      */\r
315     public boolean isIPInUse(String ipAddress) {\r
316         if (ipAddress.equals(gatewayIP) && !gatewayIPAssigned ) {\r
317             return false;\r
318         }\r
319         Iterator<NeutronSubnet_IPAllocationPool> i = allocationPools.iterator();\r
320         while (i.hasNext()) {\r
321             NeutronSubnet_IPAllocationPool pool = i.next();\r
322             if (pool.contains(ipAddress)) {\r
323                 return false;\r
324             }\r
325         }\r
326         return true;\r
327     }\r
328 \r
329     /* method to get the lowest available address of the subnet.\r
330      * go through all the allocation pools and keep the lowest of their\r
331      * low addresses.\r
332      */\r
333     public String getLowAddr() {\r
334         String ans = null;\r
335         Iterator<NeutronSubnet_IPAllocationPool> i = allocationPools.iterator();\r
336         while (i.hasNext()) {\r
337             NeutronSubnet_IPAllocationPool pool = i.next();\r
338             if (ans == null) {\r
339                 ans = pool.getPoolStart();\r
340             }\r
341             else\r
342                 if (NeutronSubnet_IPAllocationPool.convert(pool.getPoolStart()) <\r
343                         NeutronSubnet_IPAllocationPool.convert(ans)) {\r
344                     ans = pool.getPoolStart();\r
345                 }\r
346         }\r
347         return ans;\r
348     }\r
349 \r
350     /*\r
351      * allocate the parameter address.  Because this uses an iterator to\r
352      * check the instance's list of allocation pools and we want to modify\r
353      * pools while the iterator is being used, it is necessary to\r
354      * build a new list of allocation pools and replace the list when\r
355      * finished (otherwise a split will cause undefined iterator behavior.\r
356      */\r
357     public void allocateIP(String ipAddress) {\r
358         Iterator<NeutronSubnet_IPAllocationPool> i = allocationPools.iterator();\r
359         List<NeutronSubnet_IPAllocationPool> newList = new ArrayList<NeutronSubnet_IPAllocationPool>();    // we have to modify a separate list\r
360         while (i.hasNext()) {\r
361             NeutronSubnet_IPAllocationPool pool = i.next();\r
362             /* if the pool contains a single address element and we are allocating it\r
363              * then we don't need to copy the pool over.  Otherwise, we need to possibly\r
364              * split the pool and add both pieces to the new list\r
365              */\r
366             if (!(pool.getPoolEnd().equalsIgnoreCase(ipAddress) &&\r
367                     pool.getPoolStart().equalsIgnoreCase(ipAddress))) {\r
368                 if (pool.contains(ipAddress)) {\r
369                     List<NeutronSubnet_IPAllocationPool> pools = pool.splitPool(ipAddress);\r
370                     newList.addAll(pools);\r
371                 } else {\r
372                     newList.add(pool);\r
373                 }\r
374             }\r
375         }\r
376         allocationPools = newList;\r
377     }\r
378 \r
379     /*\r
380      * release an IP address back to the subnet.  Although an iterator\r
381      * is used, the list is not modified until the iterator is complete, so\r
382      * an extra list is not necessary.\r
383      */\r
384     public void releaseIP(String ipAddress) {\r
385         NeutronSubnet_IPAllocationPool lPool = null;\r
386         NeutronSubnet_IPAllocationPool hPool = null;\r
387         Iterator<NeutronSubnet_IPAllocationPool> i = allocationPools.iterator();\r
388         long sIP = NeutronSubnet_IPAllocationPool.convert(ipAddress);\r
389         //look for lPool where ipAddr - 1 is high address\r
390         //look for hPool where ipAddr + 1 is low address\r
391         while (i.hasNext()) {\r
392             NeutronSubnet_IPAllocationPool pool = i.next();\r
393             long lIP = NeutronSubnet_IPAllocationPool.convert(pool.getPoolStart());\r
394             long hIP = NeutronSubnet_IPAllocationPool.convert(pool.getPoolEnd());\r
395             if (sIP+1 == lIP) {\r
396                 hPool = pool;\r
397             }\r
398             if (sIP-1 == hIP) {\r
399                 lPool = pool;\r
400             }\r
401         }\r
402         //if (lPool == NULL and hPool == NULL) create new pool where low = ip = high\r
403         if (lPool == null && hPool == null) {\r
404             allocationPools.add(new NeutronSubnet_IPAllocationPool(ipAddress,ipAddress));\r
405         }\r
406         //if (lPool == NULL and hPool != NULL) change low address of hPool to ipAddr\r
407         if (lPool == null && hPool != null) {\r
408             hPool.setPoolStart(ipAddress);\r
409         }\r
410         //if (lPool != NULL and hPool == NULL) change high address of lPool to ipAddr\r
411         if (lPool != null && hPool == null) {\r
412             lPool.setPoolEnd(ipAddress);\r
413         }\r
414         //if (lPool != NULL and hPool != NULL) remove lPool and hPool and create new pool\r
415         //        where low address = lPool.low address and high address = hPool.high Address\r
416         if (lPool != null && hPool != null) {\r
417             allocationPools.remove(lPool);\r
418             allocationPools.remove(hPool);\r
419             allocationPools.add(new NeutronSubnet_IPAllocationPool(\r
420                     lPool.getPoolStart(), hPool.getPoolEnd()));\r
421         }\r
422     }\r
423 \r
424     public void setGatewayIPAllocated() {\r
425         gatewayIPAssigned = true;\r
426     }\r
427 \r
428     public void resetGatewayIPAllocated() {\r
429         gatewayIPAssigned = false;\r
430     }\r
431 }\r