d7919394867b0ef67b43ca7c20498f3a21df6ae7
[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         return enableDHCP;\r
151     }\r
152 \r
153     public Boolean getEnableDHCP() { return enableDHCP; }\r
154 \r
155     public void setEnableDHCP(Boolean newValue) {\r
156             this.enableDHCP = newValue;\r
157     }\r
158 \r
159     public String getTenantID() {\r
160         return tenantID;\r
161     }\r
162 \r
163     public void setTenantID(String tenantID) {\r
164         this.tenantID = tenantID;\r
165     }\r
166 \r
167     /**\r
168      * This method copies selected fields from the object and returns them\r
169      * as a new object, suitable for marshaling.\r
170      *\r
171      * @param fields\r
172      *            List of attributes to be extracted\r
173      * @return an OpenStackSubnets object with only the selected fields\r
174      * populated\r
175      */\r
176 \r
177     public NeutronSubnet extractFields(List<String> fields) {\r
178         NeutronSubnet ans = new NeutronSubnet();\r
179         Iterator<String> i = fields.iterator();\r
180         while (i.hasNext()) {\r
181             String s = i.next();\r
182             if (s.equals("id"))\r
183                 ans.setSubnetUUID(this.getSubnetUUID());\r
184             if (s.equals("network_id"))\r
185                 ans.setNetworkUUID(this.getNetworkUUID());\r
186             if (s.equals("name"))\r
187                 ans.setName(this.getName());\r
188             if (s.equals("ip_version"))\r
189                 ans.setIpVersion(this.getIpVersion());\r
190             if (s.equals("cidr"))\r
191                 ans.setCidr(this.getCidr());\r
192             if (s.equals("gateway_ip"))\r
193                 ans.setGatewayIP(this.getGatewayIP());\r
194             if (s.equals("dns_nameservers")) {\r
195                 List<String> nsList = new ArrayList<String>();\r
196                 nsList.addAll(this.getDnsNameservers());\r
197                 ans.setDnsNameservers(nsList);\r
198             }\r
199             if (s.equals("allocation_pools")) {\r
200                 List<NeutronSubnet_IPAllocationPool> aPools = new ArrayList<NeutronSubnet_IPAllocationPool>();\r
201                 aPools.addAll(this.getAllocationPools());\r
202                 ans.setAllocationPools(aPools);\r
203             }\r
204             if (s.equals("host_routes")) {\r
205                 List<NeutronSubnet_HostRoute> hRoutes = new ArrayList<NeutronSubnet_HostRoute>();\r
206                 hRoutes.addAll(this.getHostRoutes());\r
207                 ans.setHostRoutes(hRoutes);\r
208             }\r
209             if (s.equals("enable_dhcp"))\r
210                 ans.setEnableDHCP(this.getEnableDHCP());\r
211             if (s.equals("tenant_id"))\r
212                 ans.setTenantID(this.getTenantID());\r
213         }\r
214         return ans;\r
215     }\r
216 \r
217     /* test to see if the cidr address used to define this subnet\r
218      * is a valid network address (an necessary condition when creating\r
219      * a new subnet)\r
220      */\r
221     public boolean isValidCIDR() {\r
222         try {\r
223             SubnetUtils util = new SubnetUtils(cidr);\r
224             SubnetInfo info = util.getInfo();\r
225             if (!info.getNetworkAddress().equals(info.getAddress()))\r
226                 return false;\r
227         } catch (Exception e) {\r
228             return false;\r
229         }\r
230         return true;\r
231     }\r
232 \r
233     /* test to see if the gateway IP specified overlaps with specified\r
234      * allocation pools (an error condition when creating a new subnet\r
235      * or assigning a gateway IP)\r
236      */\r
237     public boolean gatewayIP_Pool_overlap() {\r
238         Iterator<NeutronSubnet_IPAllocationPool> i = allocationPools.iterator();\r
239         while (i.hasNext()) {\r
240             NeutronSubnet_IPAllocationPool pool = i.next();\r
241             if (pool.contains(gatewayIP))\r
242                 return true;\r
243         }\r
244         return false;\r
245     }\r
246 \r
247     public void initDefaults() {\r
248         if (enableDHCP == null)\r
249             enableDHCP = true;\r
250         if (ipVersion == null)\r
251             ipVersion = 4;\r
252         gatewayIPAssigned = false;\r
253         dnsNameservers = new ArrayList<String>();\r
254         allocationPools = new ArrayList<NeutronSubnet_IPAllocationPool>();\r
255         hostRoutes = new ArrayList<NeutronSubnet_HostRoute>();\r
256         try {\r
257             SubnetUtils util = new SubnetUtils(cidr);\r
258             SubnetInfo info = util.getInfo();\r
259             if (gatewayIP == null)\r
260                 gatewayIP = info.getLowAddress();\r
261             if (allocationPools.size() < 1) {\r
262                 NeutronSubnet_IPAllocationPool source =\r
263                     new NeutronSubnet_IPAllocationPool(info.getLowAddress(),\r
264                             info.getHighAddress());\r
265                 allocationPools = source.splitPool(gatewayIP);\r
266             }\r
267         } catch (Exception e) {\r
268             ;\r
269         }\r
270     }\r
271 \r
272     public List<NeutronPort> getPortsInSubnet() {\r
273         return myPorts;\r
274     }\r
275 \r
276     public void addPort(NeutronPort port) {\r
277         myPorts.add(port);\r
278     }\r
279 \r
280     public void removePort(NeutronPort port) {\r
281         myPorts.remove(port);\r
282     }\r
283 \r
284     /* this method tests to see if the supplied IPv4 address\r
285      * is valid for this subnet or not\r
286      */\r
287     public boolean isValidIP(String ipAddress) {\r
288         try {\r
289             SubnetUtils util = new SubnetUtils(cidr);\r
290             SubnetInfo info = util.getInfo();\r
291             return info.isInRange(ipAddress);\r
292         } catch (Exception e) {\r
293             return false;\r
294         }\r
295     }\r
296 \r
297     /* test to see if the supplied IPv4 address is part of one of the\r
298      * available allocation pools or not\r
299      */\r
300     public boolean isIPInUse(String ipAddress) {\r
301         if (ipAddress.equals(gatewayIP) && !gatewayIPAssigned )\r
302             return false;\r
303         Iterator<NeutronSubnet_IPAllocationPool> i = allocationPools.iterator();\r
304         while (i.hasNext()) {\r
305             NeutronSubnet_IPAllocationPool pool = i.next();\r
306             if (pool.contains(ipAddress))\r
307                 return false;\r
308         }\r
309         return true;\r
310     }\r
311 \r
312     /* method to get the lowest available address of the subnet.\r
313      * go through all the allocation pools and keep the lowest of their\r
314      * low addresses.\r
315      */\r
316     public String getLowAddr() {\r
317         String ans = null;\r
318         Iterator<NeutronSubnet_IPAllocationPool> i = allocationPools.iterator();\r
319         while (i.hasNext()) {\r
320             NeutronSubnet_IPAllocationPool pool = i.next();\r
321             if (ans == null) {\r
322                 ans = pool.getPoolStart();\r
323             }\r
324             else\r
325                 if (NeutronSubnet_IPAllocationPool.convert(pool.getPoolStart()) <\r
326                         NeutronSubnet_IPAllocationPool.convert(ans))\r
327                     ans = pool.getPoolStart();\r
328         }\r
329         return ans;\r
330     }\r
331 \r
332     /*\r
333      * allocate the parameter address.  Because this uses an iterator to\r
334      * check the instance's list of allocation pools and we want to modify\r
335      * pools while the iterator is being used, it is necessary to\r
336      * build a new list of allocation pools and replace the list when\r
337      * finished (otherwise a split will cause undefined iterator behavior.\r
338      */\r
339     public void allocateIP(String ipAddress) {\r
340         Iterator<NeutronSubnet_IPAllocationPool> i = allocationPools.iterator();\r
341         List<NeutronSubnet_IPAllocationPool> newList = new ArrayList<NeutronSubnet_IPAllocationPool>();    // we have to modify a separate list\r
342         while (i.hasNext()) {\r
343             NeutronSubnet_IPAllocationPool pool = i.next();\r
344             /* if the pool contains a single address element and we are allocating it\r
345              * then we don't need to copy the pool over.  Otherwise, we need to possibly\r
346              * split the pool and add both pieces to the new list\r
347              */\r
348             if (!(pool.getPoolEnd().equalsIgnoreCase(ipAddress) &&\r
349                     pool.getPoolStart().equalsIgnoreCase(ipAddress))) {\r
350                 if (pool.contains(ipAddress)) {\r
351                     List<NeutronSubnet_IPAllocationPool> pools = pool.splitPool(ipAddress);\r
352                     newList.addAll(pools);\r
353                 } else\r
354                     newList.add(pool);\r
355             }\r
356         }\r
357         allocationPools = newList;\r
358     }\r
359 \r
360     /*\r
361      * release an IP address back to the subnet.  Although an iterator\r
362      * is used, the list is not modified until the iterator is complete, so\r
363      * an extra list is not necessary.\r
364      */\r
365     public void releaseIP(String ipAddress) {\r
366         NeutronSubnet_IPAllocationPool lPool = null;\r
367         NeutronSubnet_IPAllocationPool hPool = null;\r
368         Iterator<NeutronSubnet_IPAllocationPool> i = allocationPools.iterator();\r
369         long sIP = NeutronSubnet_IPAllocationPool.convert(ipAddress);\r
370         //look for lPool where ipAddr - 1 is high address\r
371         //look for hPool where ipAddr + 1 is low address\r
372         while (i.hasNext()) {\r
373             NeutronSubnet_IPAllocationPool pool = i.next();\r
374             long lIP = NeutronSubnet_IPAllocationPool.convert(pool.getPoolStart());\r
375             long hIP = NeutronSubnet_IPAllocationPool.convert(pool.getPoolEnd());\r
376             if (sIP+1 == lIP)\r
377                 hPool = pool;\r
378             if (sIP-1 == hIP)\r
379                 lPool = pool;\r
380         }\r
381         //if (lPool == NULL and hPool == NULL) create new pool where low = ip = high\r
382         if (lPool == null && hPool == null)\r
383             allocationPools.add(new NeutronSubnet_IPAllocationPool(ipAddress,ipAddress));\r
384         //if (lPool == NULL and hPool != NULL) change low address of hPool to ipAddr\r
385         if (lPool == null && hPool != null)\r
386             hPool.setPoolStart(ipAddress);\r
387         //if (lPool != NULL and hPool == NULL) change high address of lPool to ipAddr\r
388         if (lPool != null && hPool == null)\r
389             lPool.setPoolEnd(ipAddress);\r
390         //if (lPool != NULL and hPool != NULL) remove lPool and hPool and create new pool\r
391         //        where low address = lPool.low address and high address = hPool.high Address\r
392         if (lPool != null && hPool != null) {\r
393             allocationPools.remove(lPool);\r
394             allocationPools.remove(hPool);\r
395             allocationPools.add(new NeutronSubnet_IPAllocationPool(\r
396                     lPool.getPoolStart(), hPool.getPoolEnd()));\r
397         }\r
398     }\r
399 \r
400     public void setGatewayIPAllocated() {\r
401         gatewayIPAssigned = true;\r
402     }\r
403 \r
404     public void resetGatewayIPAllocated() {\r
405         gatewayIPAssigned = false;\r
406     }\r
407 }\r