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