2 * Copyright IBM Corporation, 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.util.ArrayList;
12 import java.util.Iterator;
13 import java.util.List;
15 import javax.xml.bind.annotation.XmlAccessType;
16 import javax.xml.bind.annotation.XmlAccessorType;
17 import javax.xml.bind.annotation.XmlElement;
18 import javax.xml.bind.annotation.XmlRootElement;
20 import org.apache.commons.net.util.SubnetUtils;
21 import org.apache.commons.net.util.SubnetUtils.SubnetInfo;
24 @XmlAccessorType(XmlAccessType.NONE)
26 public class NeutronSubnet {
27 // See OpenStack Network API v2.0 Reference for description of
28 // annotated attributes
30 @XmlElement (name="id")
33 @XmlElement (name="network_id")
36 @XmlElement (name="name")
39 @XmlElement (defaultValue="4", name="ip_version")
42 @XmlElement (name="cidr")
45 @XmlElement (name="gateway_ip")
48 @XmlElement (name="dns_nameservers")
49 List<String> dnsNameservers;
51 @XmlElement (name="allocation_pools")
52 List<NeutronSubnet_IPAllocationPool> allocationPools;
54 @XmlElement (name="host_routes")
55 List<NeutronSubnet_HostRoute> hostRoutes;
57 @XmlElement (defaultValue="true", name="enable_dhcp")
60 @XmlElement (name="tenant_id")
63 /* stores the OpenStackPorts associated with an instance
64 * used to determine if that instance can be deleted.
66 List<NeutronPort> myPorts;
68 boolean gatewayIPAssigned;
70 public NeutronSubnet() {
71 myPorts = new ArrayList<NeutronPort>();
74 public String getID() { return subnetUUID; }
76 public String getSubnetUUID() {
80 public void setSubnetUUID(String subnetUUID) {
81 this.subnetUUID = subnetUUID;
84 public String getNetworkUUID() {
88 public void setNetworkUUID(String networkUUID) {
89 this.networkUUID = networkUUID;
92 public String getName() {
96 public void setName(String name) {
100 public Integer getIpVersion() {
104 public void setIpVersion(Integer ipVersion) {
105 this.ipVersion = ipVersion;
108 public String getCidr() {
112 public void setCidr(String cidr) {
116 public String getGatewayIP() {
120 public void setGatewayIP(String gatewayIP) {
121 this.gatewayIP = gatewayIP;
124 public List<String> getDnsNameservers() {
125 return dnsNameservers;
128 public void setDnsNameservers(List<String> dnsNameservers) {
129 this.dnsNameservers = dnsNameservers;
132 public List<NeutronSubnet_IPAllocationPool> getAllocationPools() {
133 return allocationPools;
136 public void setAllocationPools(List<NeutronSubnet_IPAllocationPool> allocationPools) {
137 this.allocationPools = allocationPools;
140 public List<NeutronSubnet_HostRoute> getHostRoutes() {
144 public void setHostRoutes(List<NeutronSubnet_HostRoute> hostRoutes) {
145 this.hostRoutes = hostRoutes;
148 public boolean isEnableDHCP() {
149 if (enableDHCP == null) {
155 public Boolean getEnableDHCP() { return enableDHCP; }
157 public void setEnableDHCP(Boolean newValue) {
158 enableDHCP = newValue;
161 public String getTenantID() {
165 public void setTenantID(String tenantID) {
166 this.tenantID = tenantID;
170 * This method copies selected fields from the object and returns them
171 * as a new object, suitable for marshaling.
174 * List of attributes to be extracted
175 * @return an OpenStackSubnets object with only the selected fields
179 public NeutronSubnet extractFields(List<String> fields) {
180 NeutronSubnet ans = new NeutronSubnet();
181 Iterator<String> i = fields.iterator();
182 while (i.hasNext()) {
184 if (s.equals("id")) {
185 ans.setSubnetUUID(this.getSubnetUUID());
187 if (s.equals("network_id")) {
188 ans.setNetworkUUID(this.getNetworkUUID());
190 if (s.equals("name")) {
191 ans.setName(this.getName());
193 if (s.equals("ip_version")) {
194 ans.setIpVersion(this.getIpVersion());
196 if (s.equals("cidr")) {
197 ans.setCidr(this.getCidr());
199 if (s.equals("gateway_ip")) {
200 ans.setGatewayIP(this.getGatewayIP());
202 if (s.equals("dns_nameservers")) {
203 List<String> nsList = new ArrayList<String>();
204 nsList.addAll(this.getDnsNameservers());
205 ans.setDnsNameservers(nsList);
207 if (s.equals("allocation_pools")) {
208 List<NeutronSubnet_IPAllocationPool> aPools = new ArrayList<NeutronSubnet_IPAllocationPool>();
209 aPools.addAll(this.getAllocationPools());
210 ans.setAllocationPools(aPools);
212 if (s.equals("host_routes")) {
213 List<NeutronSubnet_HostRoute> hRoutes = new ArrayList<NeutronSubnet_HostRoute>();
214 hRoutes.addAll(this.getHostRoutes());
215 ans.setHostRoutes(hRoutes);
217 if (s.equals("enable_dhcp")) {
218 ans.setEnableDHCP(this.getEnableDHCP());
220 if (s.equals("tenant_id")) {
221 ans.setTenantID(this.getTenantID());
227 /* test to see if the cidr address used to define this subnet
228 * is a valid network address (an necessary condition when creating
231 public boolean isValidCIDR() {
233 SubnetUtils util = new SubnetUtils(cidr);
234 SubnetInfo info = util.getInfo();
235 if (!info.getNetworkAddress().equals(info.getAddress())) {
238 } catch (Exception e) {
244 /* test to see if the gateway IP specified overlaps with specified
245 * allocation pools (an error condition when creating a new subnet
246 * or assigning a gateway IP)
248 public boolean gatewayIP_Pool_overlap() {
249 Iterator<NeutronSubnet_IPAllocationPool> i = allocationPools.iterator();
250 while (i.hasNext()) {
251 NeutronSubnet_IPAllocationPool pool = i.next();
252 if (pool.contains(gatewayIP)) {
259 public boolean initDefaults() {
260 if (enableDHCP == null) {
263 if (ipVersion == null) {
266 gatewayIPAssigned = false;
267 dnsNameservers = new ArrayList<String>();
268 allocationPools = new ArrayList<NeutronSubnet_IPAllocationPool>();
269 hostRoutes = new ArrayList<NeutronSubnet_HostRoute>();
271 SubnetUtils util = new SubnetUtils(cidr);
272 SubnetInfo info = util.getInfo();
273 if (gatewayIP == null) {
274 gatewayIP = info.getLowAddress();
276 if (allocationPools.size() < 1) {
277 NeutronSubnet_IPAllocationPool source =
278 new NeutronSubnet_IPAllocationPool(info.getLowAddress(),
279 info.getHighAddress());
280 allocationPools = source.splitPool(gatewayIP);
282 } catch (Exception e) {
288 public List<NeutronPort> getPortsInSubnet() {
292 public void addPort(NeutronPort port) {
296 public void removePort(NeutronPort port) {
297 myPorts.remove(port);
300 /* this method tests to see if the supplied IPv4 address
301 * is valid for this subnet or not
303 public boolean isValidIP(String ipAddress) {
305 SubnetUtils util = new SubnetUtils(cidr);
306 SubnetInfo info = util.getInfo();
307 return info.isInRange(ipAddress);
308 } catch (Exception e) {
313 /* test to see if the supplied IPv4 address is part of one of the
314 * available allocation pools or not
316 public boolean isIPInUse(String ipAddress) {
317 if (ipAddress.equals(gatewayIP) && !gatewayIPAssigned ) {
320 Iterator<NeutronSubnet_IPAllocationPool> i = allocationPools.iterator();
321 while (i.hasNext()) {
322 NeutronSubnet_IPAllocationPool pool = i.next();
323 if (pool.contains(ipAddress)) {
330 /* method to get the lowest available address of the subnet.
331 * go through all the allocation pools and keep the lowest of their
334 public String getLowAddr() {
336 Iterator<NeutronSubnet_IPAllocationPool> i = allocationPools.iterator();
337 while (i.hasNext()) {
338 NeutronSubnet_IPAllocationPool pool = i.next();
340 ans = pool.getPoolStart();
343 if (NeutronSubnet_IPAllocationPool.convert(pool.getPoolStart()) <
344 NeutronSubnet_IPAllocationPool.convert(ans)) {
345 ans = pool.getPoolStart();
352 * allocate the parameter address. Because this uses an iterator to
353 * check the instance's list of allocation pools and we want to modify
354 * pools while the iterator is being used, it is necessary to
355 * build a new list of allocation pools and replace the list when
356 * finished (otherwise a split will cause undefined iterator behavior.
358 public void allocateIP(String ipAddress) {
359 Iterator<NeutronSubnet_IPAllocationPool> i = allocationPools.iterator();
360 List<NeutronSubnet_IPAllocationPool> newList = new ArrayList<NeutronSubnet_IPAllocationPool>(); // we have to modify a separate list
361 while (i.hasNext()) {
362 NeutronSubnet_IPAllocationPool pool = i.next();
363 /* if the pool contains a single address element and we are allocating it
364 * then we don't need to copy the pool over. Otherwise, we need to possibly
365 * split the pool and add both pieces to the new list
367 if (!(pool.getPoolEnd().equalsIgnoreCase(ipAddress) &&
368 pool.getPoolStart().equalsIgnoreCase(ipAddress))) {
369 if (pool.contains(ipAddress)) {
370 List<NeutronSubnet_IPAllocationPool> pools = pool.splitPool(ipAddress);
371 newList.addAll(pools);
377 allocationPools = newList;
381 * release an IP address back to the subnet. Although an iterator
382 * is used, the list is not modified until the iterator is complete, so
383 * an extra list is not necessary.
385 public void releaseIP(String ipAddress) {
386 NeutronSubnet_IPAllocationPool lPool = null;
387 NeutronSubnet_IPAllocationPool hPool = null;
388 Iterator<NeutronSubnet_IPAllocationPool> i = allocationPools.iterator();
389 long sIP = NeutronSubnet_IPAllocationPool.convert(ipAddress);
390 //look for lPool where ipAddr - 1 is high address
391 //look for hPool where ipAddr + 1 is low address
392 while (i.hasNext()) {
393 NeutronSubnet_IPAllocationPool pool = i.next();
394 long lIP = NeutronSubnet_IPAllocationPool.convert(pool.getPoolStart());
395 long hIP = NeutronSubnet_IPAllocationPool.convert(pool.getPoolEnd());
403 //if (lPool == NULL and hPool == NULL) create new pool where low = ip = high
404 if (lPool == null && hPool == null) {
405 allocationPools.add(new NeutronSubnet_IPAllocationPool(ipAddress,ipAddress));
407 //if (lPool == NULL and hPool != NULL) change low address of hPool to ipAddr
408 if (lPool == null && hPool != null) {
409 hPool.setPoolStart(ipAddress);
411 //if (lPool != NULL and hPool == NULL) change high address of lPool to ipAddr
412 if (lPool != null && hPool == null) {
413 lPool.setPoolEnd(ipAddress);
415 //if (lPool != NULL and hPool != NULL) remove lPool and hPool and create new pool
416 // where low address = lPool.low address and high address = hPool.high Address
417 if (lPool != null && hPool != null) {
418 allocationPools.remove(lPool);
419 allocationPools.remove(hPool);
420 allocationPools.add(new NeutronSubnet_IPAllocationPool(
421 lPool.getPoolStart(), hPool.getPoolEnd()));
425 public void setGatewayIPAllocated() {
426 gatewayIPAssigned = true;
429 public void resetGatewayIPAllocated() {
430 gatewayIPAssigned = false;
434 public String toString() {
435 return "NeutronSubnet [subnetUUID=" + subnetUUID + ", networkUUID=" + networkUUID + ", name=" + name
436 + ", ipVersion=" + ipVersion + ", cidr=" + cidr + ", gatewayIP=" + gatewayIP + ", dnsNameservers="
437 + dnsNameservers + ", allocationPools=" + allocationPools + ", hostRoutes=" + hostRoutes
438 + ", enableDHCP=" + enableDHCP + ", tenantID=" + tenantID + ", myPorts=" + myPorts
439 + ", gatewayIPAssigned=" + gatewayIPAssigned + "]";