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