--- /dev/null
+/*\r
+ * Copyright IBM Corporation, 2013. All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+\r
+package org.opendaylight.controller.networkconfig.neutron;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Iterator;\r
+import java.util.List;\r
+import javax.xml.bind.annotation.XmlAccessType;\r
+import javax.xml.bind.annotation.XmlAccessorType;\r
+import javax.xml.bind.annotation.XmlElement;\r
+import javax.xml.bind.annotation.XmlRootElement;\r
+\r
+import org.apache.commons.net.util.SubnetUtils;\r
+import org.apache.commons.net.util.SubnetUtils.SubnetInfo;\r
+\r
+@XmlRootElement\r
+@XmlAccessorType(XmlAccessType.NONE)\r
+\r
+public class NeutronSubnet {\r
+ // See OpenStack Network API v2.0 Reference for description of\r
+ // annotated attributes\r
+\r
+ @XmlElement (name="id")\r
+ String subnetUUID;\r
+\r
+ @XmlElement (name="network_id")\r
+ String networkUUID;\r
+\r
+ @XmlElement (name="name")\r
+ String name;\r
+\r
+ @XmlElement (defaultValue="4", name="ip_version")\r
+ Integer ipVersion;\r
+\r
+ @XmlElement (name="cidr")\r
+ String cidr;\r
+\r
+ @XmlElement (name="gateway_ip")\r
+ String gatewayIP;\r
+\r
+ @XmlElement (name="dns_nameservers")\r
+ List<String> dnsNameservers;\r
+\r
+ @XmlElement (name="allocation_pools")\r
+ List<NeutronSubnet_IPAllocationPool> allocationPools;\r
+\r
+ @XmlElement (name="host_routes")\r
+ List<NeutronSubnet_HostRoute> hostRoutes;\r
+\r
+ @XmlElement (defaultValue="true", name="enable_dhcp")\r
+ Boolean enableDHCP;\r
+\r
+ @XmlElement (name="tenant_id")\r
+ String tenantID;\r
+\r
+ /* stores the OpenStackPorts associated with an instance\r
+ * used to determine if that instance can be deleted.\r
+ */\r
+ List<NeutronPort> myPorts;\r
+\r
+ boolean gatewayIPAssigned;\r
+\r
+ public NeutronSubnet() {\r
+ myPorts = new ArrayList<NeutronPort>();\r
+ }\r
+\r
+ public String getID() { return subnetUUID; }\r
+\r
+ public String getSubnetUUID() {\r
+ return subnetUUID;\r
+ }\r
+\r
+ public void setSubnetUUID(String subnetUUID) {\r
+ this.subnetUUID = subnetUUID;\r
+ }\r
+\r
+ public String getNetworkUUID() {\r
+ return networkUUID;\r
+ }\r
+\r
+ public void setNetworkUUID(String networkUUID) {\r
+ this.networkUUID = networkUUID;\r
+ }\r
+\r
+ public String getName() {\r
+ return name;\r
+ }\r
+\r
+ public void setName(String name) {\r
+ this.name = name;\r
+ }\r
+\r
+ public Integer getIpVersion() {\r
+ return ipVersion;\r
+ }\r
+\r
+ public void setIpVersion(Integer ipVersion) {\r
+ this.ipVersion = ipVersion;\r
+ }\r
+\r
+ public String getCidr() {\r
+ return cidr;\r
+ }\r
+\r
+ public void setCidr(String cidr) {\r
+ this.cidr = cidr;\r
+ }\r
+\r
+ public String getGatewayIP() {\r
+ return gatewayIP;\r
+ }\r
+\r
+ public void setGatewayIP(String gatewayIP) {\r
+ this.gatewayIP = gatewayIP;\r
+ }\r
+\r
+ public List<String> getDnsNameservers() {\r
+ return dnsNameservers;\r
+ }\r
+\r
+ public void setDnsNameservers(List<String> dnsNameservers) {\r
+ this.dnsNameservers = dnsNameservers;\r
+ }\r
+\r
+ public List<NeutronSubnet_IPAllocationPool> getAllocationPools() {\r
+ return allocationPools;\r
+ }\r
+\r
+ public void setAllocationPools(List<NeutronSubnet_IPAllocationPool> allocationPools) {\r
+ this.allocationPools = allocationPools;\r
+ }\r
+\r
+ public List<NeutronSubnet_HostRoute> getHostRoutes() {\r
+ return hostRoutes;\r
+ }\r
+\r
+ public void setHostRoutes(List<NeutronSubnet_HostRoute> hostRoutes) {\r
+ this.hostRoutes = hostRoutes;\r
+ }\r
+\r
+ public boolean isEnableDHCP() {\r
+ if (enableDHCP == null)\r
+ return true;\r
+ return enableDHCP;\r
+ }\r
+\r
+ public Boolean getEnableDHCP() { return enableDHCP; }\r
+\r
+ public void setEnableDHCP(Boolean newValue) {\r
+ this.enableDHCP = newValue;\r
+ }\r
+\r
+ public String getTenantID() {\r
+ return tenantID;\r
+ }\r
+\r
+ public void setTenantID(String tenantID) {\r
+ this.tenantID = tenantID;\r
+ }\r
+\r
+ /**\r
+ * This method copies selected fields from the object and returns them\r
+ * as a new object, suitable for marshaling.\r
+ *\r
+ * @param fields\r
+ * List of attributes to be extracted\r
+ * @return an OpenStackSubnets object with only the selected fields\r
+ * populated\r
+ */\r
+\r
+ public NeutronSubnet extractFields(List<String> fields) {\r
+ NeutronSubnet ans = new NeutronSubnet();\r
+ Iterator<String> i = fields.iterator();\r
+ while (i.hasNext()) {\r
+ String s = i.next();\r
+ if (s.equals("id"))\r
+ ans.setSubnetUUID(this.getSubnetUUID());\r
+ if (s.equals("network_id"))\r
+ ans.setNetworkUUID(this.getNetworkUUID());\r
+ if (s.equals("name"))\r
+ ans.setName(this.getName());\r
+ if (s.equals("ip_version"))\r
+ ans.setIpVersion(this.getIpVersion());\r
+ if (s.equals("cidr"))\r
+ ans.setCidr(this.getCidr());\r
+ if (s.equals("gateway_ip"))\r
+ ans.setGatewayIP(this.getGatewayIP());\r
+ if (s.equals("dns_nameservers")) {\r
+ List<String> nsList = new ArrayList<String>();\r
+ nsList.addAll(this.getDnsNameservers());\r
+ ans.setDnsNameservers(nsList);\r
+ }\r
+ if (s.equals("allocation_pools")) {\r
+ List<NeutronSubnet_IPAllocationPool> aPools = new ArrayList<NeutronSubnet_IPAllocationPool>();\r
+ aPools.addAll(this.getAllocationPools());\r
+ ans.setAllocationPools(aPools);\r
+ }\r
+ if (s.equals("host_routes")) {\r
+ List<NeutronSubnet_HostRoute> hRoutes = new ArrayList<NeutronSubnet_HostRoute>();\r
+ hRoutes.addAll(this.getHostRoutes());\r
+ ans.setHostRoutes(hRoutes);\r
+ }\r
+ if (s.equals("enable_dhcp"))\r
+ ans.setEnableDHCP(this.getEnableDHCP());\r
+ if (s.equals("tenant_id"))\r
+ ans.setTenantID(this.getTenantID());\r
+ }\r
+ return ans;\r
+ }\r
+\r
+ /* test to see if the cidr address used to define this subnet\r
+ * is a valid network address (an necessary condition when creating\r
+ * a new subnet)\r
+ */\r
+ public boolean isValidCIDR() {\r
+ try {\r
+ SubnetUtils util = new SubnetUtils(cidr);\r
+ SubnetInfo info = util.getInfo();\r
+ if (!info.getNetworkAddress().equals(info.getAddress()))\r
+ return false;\r
+ } catch (Exception e) {\r
+ return false;\r
+ }\r
+ return true;\r
+ }\r
+\r
+ /* test to see if the gateway IP specified overlaps with specified\r
+ * allocation pools (an error condition when creating a new subnet\r
+ * or assigning a gateway IP)\r
+ */\r
+ public boolean gatewayIP_Pool_overlap() {\r
+ Iterator<NeutronSubnet_IPAllocationPool> i = allocationPools.iterator();\r
+ while (i.hasNext()) {\r
+ NeutronSubnet_IPAllocationPool pool = i.next();\r
+ if (pool.contains(gatewayIP))\r
+ return true;\r
+ }\r
+ return false;\r
+ }\r
+\r
+ public void initDefaults() {\r
+ if (enableDHCP == null)\r
+ enableDHCP = true;\r
+ if (ipVersion == null)\r
+ ipVersion = 4;\r
+ gatewayIPAssigned = false;\r
+ dnsNameservers = new ArrayList<String>();\r
+ allocationPools = new ArrayList<NeutronSubnet_IPAllocationPool>();\r
+ hostRoutes = new ArrayList<NeutronSubnet_HostRoute>();\r
+ try {\r
+ SubnetUtils util = new SubnetUtils(cidr);\r
+ SubnetInfo info = util.getInfo();\r
+ if (gatewayIP == null)\r
+ gatewayIP = info.getLowAddress();\r
+ if (allocationPools.size() < 1) {\r
+ NeutronSubnet_IPAllocationPool source =\r
+ new NeutronSubnet_IPAllocationPool(info.getLowAddress(),\r
+ info.getHighAddress());\r
+ allocationPools = source.splitPool(gatewayIP);\r
+ }\r
+ } catch (Exception e) {\r
+ ;\r
+ }\r
+ }\r
+\r
+ public List<NeutronPort> getPortsInSubnet() {\r
+ return myPorts;\r
+ }\r
+\r
+ public void addPort(NeutronPort port) {\r
+ myPorts.add(port);\r
+ }\r
+\r
+ public void removePort(NeutronPort port) {\r
+ myPorts.remove(port);\r
+ }\r
+\r
+ /* this method tests to see if the supplied IPv4 address\r
+ * is valid for this subnet or not\r
+ */\r
+ public boolean isValidIP(String ipAddress) {\r
+ try {\r
+ SubnetUtils util = new SubnetUtils(cidr);\r
+ SubnetInfo info = util.getInfo();\r
+ return info.isInRange(ipAddress);\r
+ } catch (Exception e) {\r
+ return false;\r
+ }\r
+ }\r
+\r
+ /* test to see if the supplied IPv4 address is part of one of the\r
+ * available allocation pools or not\r
+ */\r
+ public boolean isIPInUse(String ipAddress) {\r
+ if (ipAddress.equals(gatewayIP) && !gatewayIPAssigned )\r
+ return false;\r
+ Iterator<NeutronSubnet_IPAllocationPool> i = allocationPools.iterator();\r
+ while (i.hasNext()) {\r
+ NeutronSubnet_IPAllocationPool pool = i.next();\r
+ if (pool.contains(ipAddress))\r
+ return false;\r
+ }\r
+ return true;\r
+ }\r
+\r
+ /* method to get the lowest available address of the subnet.\r
+ * go through all the allocation pools and keep the lowest of their\r
+ * low addresses.\r
+ */\r
+ public String getLowAddr() {\r
+ String ans = null;\r
+ Iterator<NeutronSubnet_IPAllocationPool> i = allocationPools.iterator();\r
+ while (i.hasNext()) {\r
+ NeutronSubnet_IPAllocationPool pool = i.next();\r
+ if (ans == null)\r
+ ans = pool.getPoolStart();\r
+ else\r
+ if (NeutronSubnet_IPAllocationPool.convert(pool.getPoolStart()) <\r
+ NeutronSubnet_IPAllocationPool.convert(ans))\r
+ ans = pool.getPoolStart();\r
+ }\r
+ return ans;\r
+ }\r
+\r
+ /*\r
+ * allocate the parameter address. Because this uses an iterator to\r
+ * check the instance's list of allocation pools and we want to modify\r
+ * pools while the iterator is being used, it is necessary to\r
+ * build a new list of allocation pools and replace the list when\r
+ * finished (otherwise a split will cause undefined iterator behavior.\r
+ */\r
+ public void allocateIP(String ipAddress) {\r
+ Iterator<NeutronSubnet_IPAllocationPool> i = allocationPools.iterator();\r
+ List<NeutronSubnet_IPAllocationPool> newList = new ArrayList<NeutronSubnet_IPAllocationPool>(); // we have to modify a separate list\r
+ while (i.hasNext()) {\r
+ NeutronSubnet_IPAllocationPool pool = i.next();\r
+ if (pool.getPoolEnd().equalsIgnoreCase(ipAddress) &&\r
+ pool.getPoolStart().equalsIgnoreCase(ipAddress))\r
+ ; // do nothing, i.e. don't add the current pool to the new list\r
+ else\r
+ if (pool.contains(ipAddress)) {\r
+ List<NeutronSubnet_IPAllocationPool> pools = pool.splitPool(ipAddress);\r
+ newList.addAll(pools);\r
+ } else\r
+ newList.add(pool);\r
+ }\r
+ allocationPools = newList;\r
+ }\r
+\r
+ /*\r
+ * release an IP address back to the subnet. Although an iterator\r
+ * is used, the list is not modified until the iterator is complete, so\r
+ * an extra list is not necessary.\r
+ */\r
+ public void releaseIP(String ipAddress) {\r
+ NeutronSubnet_IPAllocationPool lPool = null;\r
+ NeutronSubnet_IPAllocationPool hPool = null;\r
+ Iterator<NeutronSubnet_IPAllocationPool> i = allocationPools.iterator();\r
+ long sIP = NeutronSubnet_IPAllocationPool.convert(ipAddress);\r
+ //look for lPool where ipAddr - 1 is high address\r
+ //look for hPool where ipAddr + 1 is low address\r
+ while (i.hasNext()) {\r
+ NeutronSubnet_IPAllocationPool pool = i.next();\r
+ long lIP = NeutronSubnet_IPAllocationPool.convert(pool.getPoolStart());\r
+ long hIP = NeutronSubnet_IPAllocationPool.convert(pool.getPoolEnd());\r
+ if (sIP+1 == lIP)\r
+ hPool = pool;\r
+ if (sIP-1 == hIP)\r
+ lPool = pool;\r
+ }\r
+ //if (lPool == NULL and hPool == NULL) create new pool where low = ip = high\r
+ if (lPool == null && hPool == null)\r
+ allocationPools.add(new NeutronSubnet_IPAllocationPool(ipAddress,ipAddress));\r
+ //if (lPool == NULL and hPool != NULL) change low address of hPool to ipAddr\r
+ if (lPool == null && hPool != null)\r
+ hPool.setPoolStart(ipAddress);\r
+ //if (lPool != NULL and hPool == NULL) change high address of lPool to ipAddr\r
+ if (lPool != null && hPool == null)\r
+ lPool.setPoolEnd(ipAddress);\r
+ //if (lPool != NULL and hPool != NULL) remove lPool and hPool and create new pool\r
+ // where low address = lPool.low address and high address = hPool.high Address\r
+ if (lPool != null && hPool != null) {\r
+ allocationPools.remove(lPool);\r
+ allocationPools.remove(hPool);\r
+ allocationPools.add(new NeutronSubnet_IPAllocationPool(\r
+ lPool.getPoolStart(), hPool.getPoolEnd()));\r
+ }\r
+ }\r
+\r
+ public void setGatewayIPAllocated() {\r
+ gatewayIPAssigned = true;\r
+ }\r
+\r
+ public void resetGatewayIPAllocated() {\r
+ gatewayIPAssigned = false;\r
+ }\r
+}\r