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.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;
25 @XmlAccessorType(XmlAccessType.NONE)
27 public class NeutronSubnet implements Serializable {
28 private static final long serialVersionUID = 1L;
30 // See OpenStack Network API v2.0 Reference for description of
31 // annotated attributes
33 @XmlElement (name="id")
36 @XmlElement (name="network_id")
39 @XmlElement (name="name")
42 @XmlElement (defaultValue="4", name="ip_version")
45 @XmlElement (name="cidr")
48 @XmlElement (name="gateway_ip")
51 @XmlElement (name="dns_nameservers")
52 List<String> dnsNameservers;
54 @XmlElement (name="allocation_pools")
55 List<NeutronSubnet_IPAllocationPool> allocationPools;
57 @XmlElement (name="host_routes")
58 List<NeutronSubnet_HostRoute> hostRoutes;
60 @XmlElement (defaultValue="true", name="enable_dhcp")
63 @XmlElement (name="tenant_id")
66 /* stores the OpenStackPorts associated with an instance
67 * used to determine if that instance can be deleted.
69 List<NeutronPort> myPorts;
71 boolean gatewayIPAssigned;
73 public NeutronSubnet() {
74 myPorts = new ArrayList<NeutronPort>();
77 public String getID() { return subnetUUID; }
79 public String getSubnetUUID() {
83 public void setSubnetUUID(String subnetUUID) {
84 this.subnetUUID = subnetUUID;
87 public String getNetworkUUID() {
91 public void setNetworkUUID(String networkUUID) {
92 this.networkUUID = networkUUID;
95 public String getName() {
99 public void setName(String name) {
103 public Integer getIpVersion() {
107 public void setIpVersion(Integer ipVersion) {
108 this.ipVersion = ipVersion;
111 public String getCidr() {
115 public void setCidr(String cidr) {
119 public String getGatewayIP() {
123 public void setGatewayIP(String gatewayIP) {
124 this.gatewayIP = gatewayIP;
127 public List<String> getDnsNameservers() {
128 return dnsNameservers;
131 public void setDnsNameservers(List<String> dnsNameservers) {
132 this.dnsNameservers = dnsNameservers;
135 public List<NeutronSubnet_IPAllocationPool> getAllocationPools() {
136 return allocationPools;
139 public void setAllocationPools(List<NeutronSubnet_IPAllocationPool> allocationPools) {
140 this.allocationPools = allocationPools;
143 public List<NeutronSubnet_HostRoute> getHostRoutes() {
147 public void setHostRoutes(List<NeutronSubnet_HostRoute> hostRoutes) {
148 this.hostRoutes = hostRoutes;
151 public boolean isEnableDHCP() {
152 if (enableDHCP == null) {
158 public Boolean getEnableDHCP() { return enableDHCP; }
160 public void setEnableDHCP(Boolean newValue) {
161 enableDHCP = newValue;
164 public String getTenantID() {
168 public void setTenantID(String tenantID) {
169 this.tenantID = tenantID;
173 * This method copies selected fields from the object and returns them
174 * as a new object, suitable for marshaling.
177 * List of attributes to be extracted
178 * @return an OpenStackSubnets object with only the selected fields
182 public NeutronSubnet extractFields(List<String> fields) {
183 NeutronSubnet ans = new NeutronSubnet();
184 Iterator<String> i = fields.iterator();
185 while (i.hasNext()) {
187 if (s.equals("id")) {
188 ans.setSubnetUUID(this.getSubnetUUID());
190 if (s.equals("network_id")) {
191 ans.setNetworkUUID(this.getNetworkUUID());
193 if (s.equals("name")) {
194 ans.setName(this.getName());
196 if (s.equals("ip_version")) {
197 ans.setIpVersion(this.getIpVersion());
199 if (s.equals("cidr")) {
200 ans.setCidr(this.getCidr());
202 if (s.equals("gateway_ip")) {
203 ans.setGatewayIP(this.getGatewayIP());
205 if (s.equals("dns_nameservers")) {
206 List<String> nsList = new ArrayList<String>();
207 nsList.addAll(this.getDnsNameservers());
208 ans.setDnsNameservers(nsList);
210 if (s.equals("allocation_pools")) {
211 List<NeutronSubnet_IPAllocationPool> aPools = new ArrayList<NeutronSubnet_IPAllocationPool>();
212 aPools.addAll(this.getAllocationPools());
213 ans.setAllocationPools(aPools);
215 if (s.equals("host_routes")) {
216 List<NeutronSubnet_HostRoute> hRoutes = new ArrayList<NeutronSubnet_HostRoute>();
217 hRoutes.addAll(this.getHostRoutes());
218 ans.setHostRoutes(hRoutes);
220 if (s.equals("enable_dhcp")) {
221 ans.setEnableDHCP(this.getEnableDHCP());
223 if (s.equals("tenant_id")) {
224 ans.setTenantID(this.getTenantID());
230 /* test to see if the cidr address used to define this subnet
231 * is a valid network address (an necessary condition when creating
234 public boolean isValidCIDR() {
236 SubnetUtils util = new SubnetUtils(cidr);
237 SubnetInfo info = util.getInfo();
238 if (!info.getNetworkAddress().equals(info.getAddress())) {
241 } catch (Exception e) {
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)
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)) {
262 public boolean initDefaults() {
263 if (enableDHCP == null) {
266 if (ipVersion == null) {
269 gatewayIPAssigned = false;
270 dnsNameservers = new ArrayList<String>();
271 allocationPools = new ArrayList<NeutronSubnet_IPAllocationPool>();
272 hostRoutes = new ArrayList<NeutronSubnet_HostRoute>();
274 SubnetUtils util = new SubnetUtils(cidr);
275 SubnetInfo info = util.getInfo();
276 if (gatewayIP == null) {
277 gatewayIP = info.getLowAddress();
279 if (allocationPools.size() < 1) {
280 NeutronSubnet_IPAllocationPool source =
281 new NeutronSubnet_IPAllocationPool(info.getLowAddress(),
282 info.getHighAddress());
283 allocationPools = source.splitPool(gatewayIP);
285 } catch (Exception e) {
291 public List<NeutronPort> getPortsInSubnet() {
295 public void addPort(NeutronPort port) {
299 public void removePort(NeutronPort port) {
300 myPorts.remove(port);
303 /* this method tests to see if the supplied IPv4 address
304 * is valid for this subnet or not
306 public boolean isValidIP(String ipAddress) {
308 SubnetUtils util = new SubnetUtils(cidr);
309 SubnetInfo info = util.getInfo();
310 return info.isInRange(ipAddress);
311 } catch (Exception e) {
316 /* test to see if the supplied IPv4 address is part of one of the
317 * available allocation pools or not
319 public boolean isIPInUse(String ipAddress) {
320 if (ipAddress.equals(gatewayIP) && !gatewayIPAssigned ) {
323 Iterator<NeutronSubnet_IPAllocationPool> i = allocationPools.iterator();
324 while (i.hasNext()) {
325 NeutronSubnet_IPAllocationPool pool = i.next();
326 if (pool.contains(ipAddress)) {
333 /* method to get the lowest available address of the subnet.
334 * go through all the allocation pools and keep the lowest of their
337 public String getLowAddr() {
339 Iterator<NeutronSubnet_IPAllocationPool> i = allocationPools.iterator();
340 while (i.hasNext()) {
341 NeutronSubnet_IPAllocationPool pool = i.next();
343 ans = pool.getPoolStart();
346 if (NeutronSubnet_IPAllocationPool.convert(pool.getPoolStart()) <
347 NeutronSubnet_IPAllocationPool.convert(ans)) {
348 ans = pool.getPoolStart();
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.
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
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);
380 allocationPools = newList;
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.
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());
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));
410 //if (lPool == NULL and hPool != NULL) change low address of hPool to ipAddr
411 if (lPool == null && hPool != null) {
412 hPool.setPoolStart(ipAddress);
414 //if (lPool != NULL and hPool == NULL) change high address of lPool to ipAddr
415 if (lPool != null && hPool == null) {
416 lPool.setPoolEnd(ipAddress);
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()));
428 public void setGatewayIPAllocated() {
429 gatewayIPAssigned = true;
432 public void resetGatewayIPAllocated() {
433 gatewayIPAssigned = false;
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 + "]";