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

©2013 OpenDaylight, A Linux Foundation Collaborative Project. All Rights Reserved.
OpenDaylight is a registered trademark of The OpenDaylight Project, Inc.
Linux Foundation and OpenDaylight are registered trademarks of the Linux Foundation.
Linux is a registered trademark of Linus Torvalds.