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