2 * Copyright IBM Corporation and others, 2013. All rights reserved.
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
9 package org.opendaylight.controller.networkconfig.neutron;
11 import java.io.Serializable;
12 import java.util.ArrayList;
13 import java.util.Iterator;
14 import java.util.List;
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;
21 import org.apache.commons.net.util.SubnetUtils;
22 import org.apache.commons.net.util.SubnetUtils.SubnetInfo;
23 import org.opendaylight.controller.configuration.ConfigurationObject;
26 @XmlAccessorType(XmlAccessType.NONE)
28 public class NeutronSubnet extends ConfigurationObject implements Serializable, INeutronObject {
29 private static final long serialVersionUID = 1L;
31 // See OpenStack Network API v2.0 Reference for description of
32 // annotated attributes
34 @XmlElement (name="id")
37 @XmlElement (name="network_id")
40 @XmlElement (name="name")
43 @XmlElement (defaultValue="4", name="ip_version")
46 @XmlElement (name="cidr")
49 @XmlElement (name="gateway_ip")
52 @XmlElement (name="dns_nameservers")
53 List<String> dnsNameservers;
55 @XmlElement (name="allocation_pools")
56 List<NeutronSubnet_IPAllocationPool> allocationPools;
58 @XmlElement (name="host_routes")
59 List<NeutronSubnet_HostRoute> hostRoutes;
61 @XmlElement (defaultValue="true", name="enable_dhcp")
64 @XmlElement (name="tenant_id")
67 @XmlElement (name="ipv6_address_mode", nillable=true)
68 String ipV6AddressMode;
70 @XmlElement (name="ipv6_ra_mode", nillable=true)
73 /* stores the OpenStackPorts associated with an instance
74 * used to determine if that instance can be deleted.
76 List<NeutronPort> myPorts;
78 Boolean gatewayIPAssigned;
80 public NeutronSubnet() {
81 myPorts = new ArrayList<NeutronPort>();
84 public String getID() { return subnetUUID; }
86 public void setID(String id) { this.subnetUUID = id; }
88 public String getSubnetUUID() {
92 public void setSubnetUUID(String subnetUUID) {
93 this.subnetUUID = subnetUUID;
96 public String getNetworkUUID() {
100 public void setNetworkUUID(String networkUUID) {
101 this.networkUUID = networkUUID;
104 public String getName() {
108 public void setName(String name) {
112 public Integer getIpVersion() {
116 public void setIpVersion(Integer ipVersion) {
117 this.ipVersion = ipVersion;
120 public String getCidr() {
124 public void setCidr(String cidr) {
128 public String getGatewayIP() {
132 public void setGatewayIP(String gatewayIP) {
133 this.gatewayIP = gatewayIP;
136 public List<String> getDnsNameservers() {
137 return dnsNameservers;
140 public void setDnsNameservers(List<String> dnsNameservers) {
141 this.dnsNameservers = dnsNameservers;
144 public List<NeutronSubnet_IPAllocationPool> getAllocationPools() {
145 return allocationPools;
148 public void setAllocationPools(List<NeutronSubnet_IPAllocationPool> allocationPools) {
149 this.allocationPools = allocationPools;
152 public List<NeutronSubnet_HostRoute> getHostRoutes() {
156 public void setHostRoutes(List<NeutronSubnet_HostRoute> hostRoutes) {
157 this.hostRoutes = hostRoutes;
160 public boolean isEnableDHCP() {
161 if (enableDHCP == null) {
167 public Boolean getEnableDHCP() { return enableDHCP; }
169 public void setEnableDHCP(Boolean newValue) {
170 enableDHCP = newValue;
173 public String getTenantID() {
177 public void setTenantID(String tenantID) {
178 this.tenantID = tenantID;
181 public String getIpV6AddressMode() { return ipV6AddressMode; }
183 public void setIpV6AddressMode(String ipV6AddressMode) { this.ipV6AddressMode = ipV6AddressMode; }
185 public String getIpV6RaMode() { return ipV6RaMode; }
187 public void setIpV6RaMode(String ipV6RaMode) { this.ipV6RaMode = ipV6RaMode; }
190 * This method copies selected fields from the object and returns them
191 * as a new object, suitable for marshaling.
194 * List of attributes to be extracted
195 * @return an OpenStackSubnets object with only the selected fields
199 public NeutronSubnet extractFields(List<String> fields) {
200 NeutronSubnet ans = new NeutronSubnet();
201 Iterator<String> i = fields.iterator();
202 while (i.hasNext()) {
204 if (s.equals("id")) {
205 ans.setSubnetUUID(this.getSubnetUUID());
207 if (s.equals("network_id")) {
208 ans.setNetworkUUID(this.getNetworkUUID());
210 if (s.equals("name")) {
211 ans.setName(this.getName());
213 if (s.equals("ip_version")) {
214 ans.setIpVersion(this.getIpVersion());
216 if (s.equals("cidr")) {
217 ans.setCidr(this.getCidr());
219 if (s.equals("gateway_ip")) {
220 ans.setGatewayIP(this.getGatewayIP());
222 if (s.equals("dns_nameservers")) {
223 List<String> nsList = new ArrayList<String>();
224 nsList.addAll(this.getDnsNameservers());
225 ans.setDnsNameservers(nsList);
227 if (s.equals("allocation_pools")) {
228 List<NeutronSubnet_IPAllocationPool> aPools = new ArrayList<NeutronSubnet_IPAllocationPool>();
229 aPools.addAll(this.getAllocationPools());
230 ans.setAllocationPools(aPools);
232 if (s.equals("host_routes")) {
233 List<NeutronSubnet_HostRoute> hRoutes = new ArrayList<NeutronSubnet_HostRoute>();
234 hRoutes.addAll(this.getHostRoutes());
235 ans.setHostRoutes(hRoutes);
237 if (s.equals("enable_dhcp")) {
238 ans.setEnableDHCP(this.getEnableDHCP());
240 if (s.equals("tenant_id")) {
241 ans.setTenantID(this.getTenantID());
243 if (s.equals("ipv6_address_mode")) {
244 ans.setIpV6AddressMode(this.getIpV6AddressMode());
246 if (s.equals("ipv6_ra_mode")) {
247 ans.setIpV6RaMode(this.getIpV6RaMode());
253 /* test to see if the cidr address used to define this subnet
254 * is a valid network address (an necessary condition when creating
257 public boolean isValidCIDR() {
259 SubnetUtils util = new SubnetUtils(cidr);
260 SubnetInfo info = util.getInfo();
261 if (!info.getNetworkAddress().equals(info.getAddress())) {
264 } catch (Exception e) {
270 /* test to see if the gateway IP specified overlaps with specified
271 * allocation pools (an error condition when creating a new subnet
272 * or assigning a gateway IP)
274 public boolean gatewayIP_Pool_overlap() {
275 Iterator<NeutronSubnet_IPAllocationPool> i = allocationPools.iterator();
276 while (i.hasNext()) {
277 NeutronSubnet_IPAllocationPool pool = i.next();
278 if (pool.contains(gatewayIP)) {
285 public boolean initDefaults() {
286 if (enableDHCP == null) {
289 if (ipVersion == null) {
292 gatewayIPAssigned = false;
293 dnsNameservers = new ArrayList<String>();
294 if (hostRoutes == null) {
295 hostRoutes = new ArrayList<NeutronSubnet_HostRoute>();
297 if (allocationPools == null) {
298 allocationPools = new ArrayList<NeutronSubnet_IPAllocationPool>();
300 SubnetUtils util = new SubnetUtils(cidr);
301 SubnetInfo info = util.getInfo();
302 if (gatewayIP == null || ("").equals(gatewayIP)) {
303 gatewayIP = info.getLowAddress();
305 if (allocationPools.size() < 1) {
306 NeutronSubnet_IPAllocationPool source =
307 new NeutronSubnet_IPAllocationPool(info.getLowAddress(),
308 info.getHighAddress());
309 allocationPools = source.splitPool(gatewayIP);
311 } catch (Exception e) {
318 public List<NeutronPort> getPortsInSubnet() {
322 public void addPort(NeutronPort port) {
326 public void removePort(NeutronPort port) {
327 myPorts.remove(port);
330 /* this method tests to see if the supplied IPv4 address
331 * is valid for this subnet or not
333 public boolean isValidIP(String ipAddress) {
335 SubnetUtils util = new SubnetUtils(cidr);
336 SubnetInfo info = util.getInfo();
337 return info.isInRange(ipAddress);
338 } catch (Exception e) {
343 /* test to see if the supplied IPv4 address is part of one of the
344 * available allocation pools or not
346 public boolean isIPInUse(String ipAddress) {
347 if (ipAddress.equals(gatewayIP) && !gatewayIPAssigned ) {
350 Iterator<NeutronSubnet_IPAllocationPool> i = allocationPools.iterator();
351 while (i.hasNext()) {
352 NeutronSubnet_IPAllocationPool pool = i.next();
353 if (pool.contains(ipAddress)) {
360 /* method to get the lowest available address of the subnet.
361 * go through all the allocation pools and keep the lowest of their
364 public String getLowAddr() {
366 Iterator<NeutronSubnet_IPAllocationPool> i = allocationPools.iterator();
367 while (i.hasNext()) {
368 NeutronSubnet_IPAllocationPool pool = i.next();
370 ans = pool.getPoolStart();
373 if (NeutronSubnet_IPAllocationPool.convert(pool.getPoolStart()) <
374 NeutronSubnet_IPAllocationPool.convert(ans)) {
375 ans = pool.getPoolStart();
382 * allocate the parameter address. Because this uses an iterator to
383 * check the instance's list of allocation pools and we want to modify
384 * pools while the iterator is being used, it is necessary to
385 * build a new list of allocation pools and replace the list when
386 * finished (otherwise a split will cause undefined iterator behavior.
388 public void allocateIP(String ipAddress) {
389 Iterator<NeutronSubnet_IPAllocationPool> i = allocationPools.iterator();
390 List<NeutronSubnet_IPAllocationPool> newList = new ArrayList<NeutronSubnet_IPAllocationPool>(); // we have to modify a separate list
391 while (i.hasNext()) {
392 NeutronSubnet_IPAllocationPool pool = i.next();
393 /* if the pool contains a single address element and we are allocating it
394 * then we don't need to copy the pool over. Otherwise, we need to possibly
395 * split the pool and add both pieces to the new list
397 if (!(pool.getPoolEnd().equalsIgnoreCase(ipAddress) &&
398 pool.getPoolStart().equalsIgnoreCase(ipAddress))) {
399 if (pool.contains(ipAddress)) {
400 List<NeutronSubnet_IPAllocationPool> pools = pool.splitPool(ipAddress);
401 newList.addAll(pools);
407 allocationPools = newList;
411 * release an IP address back to the subnet. Although an iterator
412 * is used, the list is not modified until the iterator is complete, so
413 * an extra list is not necessary.
415 public void releaseIP(String ipAddress) {
416 NeutronSubnet_IPAllocationPool lPool = null;
417 NeutronSubnet_IPAllocationPool hPool = null;
418 Iterator<NeutronSubnet_IPAllocationPool> i = allocationPools.iterator();
419 long sIP = NeutronSubnet_IPAllocationPool.convert(ipAddress);
420 //look for lPool where ipAddr - 1 is high address
421 //look for hPool where ipAddr + 1 is low address
422 while (i.hasNext()) {
423 NeutronSubnet_IPAllocationPool pool = i.next();
424 long lIP = NeutronSubnet_IPAllocationPool.convert(pool.getPoolStart());
425 long hIP = NeutronSubnet_IPAllocationPool.convert(pool.getPoolEnd());
433 //if (lPool == NULL and hPool == NULL) create new pool where low = ip = high
434 if (lPool == null && hPool == null) {
435 allocationPools.add(new NeutronSubnet_IPAllocationPool(ipAddress,ipAddress));
437 //if (lPool == NULL and hPool != NULL) change low address of hPool to ipAddr
438 if (lPool == null && hPool != null) {
439 hPool.setPoolStart(ipAddress);
441 //if (lPool != NULL and hPool == NULL) change high address of lPool to ipAddr
442 if (lPool != null && hPool == null) {
443 lPool.setPoolEnd(ipAddress);
445 //if (lPool != NULL and hPool != NULL) remove lPool and hPool and create new pool
446 // where low address = lPool.low address and high address = hPool.high Address
447 if (lPool != null && hPool != null) {
448 allocationPools.remove(lPool);
449 allocationPools.remove(hPool);
450 allocationPools.add(new NeutronSubnet_IPAllocationPool(
451 lPool.getPoolStart(), hPool.getPoolEnd()));
455 public void setGatewayIPAllocated() {
456 gatewayIPAssigned = true;
459 public void resetGatewayIPAllocated() {
460 gatewayIPAssigned = false;
463 public Boolean getGatewayIPAllocated() {
464 return gatewayIPAssigned;
468 public String toString() {
469 return "NeutronSubnet [subnetUUID=" + subnetUUID + ", networkUUID=" + networkUUID + ", name=" + name
470 + ", ipVersion=" + ipVersion + ", cidr=" + cidr + ", gatewayIP=" + gatewayIP + ", dnsNameservers="
471 + dnsNameservers + ", allocationPools=" + allocationPools + ", hostRoutes=" + hostRoutes
472 + ", enableDHCP=" + enableDHCP + ", tenantID=" + tenantID + ", myPorts=" + myPorts
473 + ", gatewayIPAssigned=" + gatewayIPAssigned + ", ipv6AddressMode=" + ipV6AddressMode
474 + ", ipv6RaMode=" + ipV6RaMode + "]";