From e40d69673c2529d99069a8a0bafb152a1c11c41a Mon Sep 17 00:00:00 2001 From: Ryan Moats Date: Fri, 20 Sep 2013 12:51:39 -0500 Subject: [PATCH] Initial push of Neutron interface Two bundles included in this: -networkconfig.neutron (contains JAXB annotated classes, *CRUD interfaces with an implementation [for storing objects], and Aware interfaces [for other bundles to register services]) -networkconfig.neutron.northbound (contains the JAXRS annotated classes along with JAXB annotated request specific classes) Commit amended to refactor .internal package to separate implementation bundle and package Commit re-amended to clean up issues in commons/opendaylight and distribution/opendaylight poms Commit re-re-amended to fix conflicts on rebase (I hope) Getting close to just abandoning the change and starting over Commit re-re-re-amended to fix parent issues in pom amend to remove leaked CRs in distribution pom - Cleanup of some duplicates artifact and of commons-net in modules dependencies, anyway they get in via the commons.opendaylight Change-Id: I15724c55e843237c010dfaec1e1e523560174f51 Signed-off-by: Ryan Moats --- opendaylight/commons/opendaylight/pom.xml | 20 + .../distribution/opendaylight/pom.xml | 5 + .../neutron/implementation/pom.xml | 81 +++ .../neutron/implementation/Activator.java | 141 +++++ .../NeutronFloatingIPInterface.java | 266 +++++++++ .../NeutronNetworkInterface.java | 227 +++++++ .../implementation/NeutronPortInterface.java | 313 ++++++++++ .../NeutronRouterInterface.java | 224 +++++++ .../NeutronSubnetInterface.java | 238 ++++++++ .../networkconfiguration/neutron/pom.xml | 71 +++ .../neutron/INeutronFloatingIPAware.java | 83 +++ .../neutron/INeutronFloatingIPCRUD.java | 83 +++ .../neutron/INeutronNetworkAware.java | 83 +++ .../neutron/INeutronNetworkCRUD.java | 95 +++ .../neutron/INeutronPortAware.java | 83 +++ .../neutron/INeutronPortCRUD.java | 105 ++++ .../neutron/INeutronRouterAware.java | 105 ++++ .../neutron/INeutronRouterCRUD.java | 93 +++ .../neutron/INeutronSubnetAware.java | 84 +++ .../neutron/INeutronSubnetCRUD.java | 95 +++ .../neutron/NeutronCRUDInterfaces.java | 39 ++ .../neutron/NeutronFloatingIP.java | 130 +++++ .../networkconfig/neutron/NeutronNetwork.java | 233 ++++++++ .../networkconfig/neutron/NeutronPort.java | 239 ++++++++ .../networkconfig/neutron/NeutronRouter.java | 153 +++++ .../neutron/NeutronRouter_Interface.java | 65 +++ .../NeutronRouter_NetworkReference.java | 36 ++ .../networkconfig/neutron/NeutronSubnet.java | 403 +++++++++++++ .../neutron/NeutronSubnet_HostRoute.java | 29 + .../NeutronSubnet_IPAllocationPool.java | 171 ++++++ .../networkconfig/neutron/Neutron_IPs.java | 49 ++ .../neutron/enunciate.xml | 12 + .../networkconfiguration/neutron/pom.xml | 120 ++++ .../northbound/NeutronFloatingIPRequest.java | 52 ++ .../NeutronFloatingIPsNorthbound.java | 427 ++++++++++++++ .../northbound/NeutronNBInterfaces.java | 193 ++++++ .../northbound/NeutronNetworkRequest.java | 55 ++ .../northbound/NeutronNetworksNorthbound.java | 355 +++++++++++ .../NeutronNorthboundRSApplication.java | 63 ++ .../northbound/NeutronPortRequest.java | 55 ++ .../northbound/NeutronPortsNorthbound.java | 476 +++++++++++++++ .../northbound/NeutronRouterRequest.java | 57 ++ .../northbound/NeutronRoutersNorthbound.java | 552 ++++++++++++++++++ .../northbound/NeutronSubnetRequest.java | 56 ++ .../northbound/NeutronSubnetsNorthbound.java | 385 ++++++++++++ .../src/main/resources/WEB-INF/web.xml | 49 ++ .../neutron/northbound/jaxb.properties | 1 + 47 files changed, 6950 insertions(+) create mode 100644 opendaylight/networkconfiguration/neutron/implementation/pom.xml create mode 100644 opendaylight/networkconfiguration/neutron/implementation/src/main/java/org/opendaylight/controller/networkconfig/neutron/implementation/Activator.java create mode 100644 opendaylight/networkconfiguration/neutron/implementation/src/main/java/org/opendaylight/controller/networkconfig/neutron/implementation/NeutronFloatingIPInterface.java create mode 100644 opendaylight/networkconfiguration/neutron/implementation/src/main/java/org/opendaylight/controller/networkconfig/neutron/implementation/NeutronNetworkInterface.java create mode 100644 opendaylight/networkconfiguration/neutron/implementation/src/main/java/org/opendaylight/controller/networkconfig/neutron/implementation/NeutronPortInterface.java create mode 100644 opendaylight/networkconfiguration/neutron/implementation/src/main/java/org/opendaylight/controller/networkconfig/neutron/implementation/NeutronRouterInterface.java create mode 100644 opendaylight/networkconfiguration/neutron/implementation/src/main/java/org/opendaylight/controller/networkconfig/neutron/implementation/NeutronSubnetInterface.java create mode 100644 opendaylight/networkconfiguration/neutron/pom.xml create mode 100644 opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronFloatingIPAware.java create mode 100644 opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronFloatingIPCRUD.java create mode 100644 opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronNetworkAware.java create mode 100644 opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronNetworkCRUD.java create mode 100644 opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronPortAware.java create mode 100644 opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronPortCRUD.java create mode 100644 opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronRouterAware.java create mode 100644 opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronRouterCRUD.java create mode 100644 opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronSubnetAware.java create mode 100644 opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronSubnetCRUD.java create mode 100644 opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronCRUDInterfaces.java create mode 100644 opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronFloatingIP.java create mode 100644 opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronNetwork.java create mode 100644 opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronPort.java create mode 100644 opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronRouter.java create mode 100644 opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronRouter_Interface.java create mode 100644 opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronRouter_NetworkReference.java create mode 100644 opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronSubnet.java create mode 100644 opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronSubnet_HostRoute.java create mode 100644 opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronSubnet_IPAllocationPool.java create mode 100644 opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/Neutron_IPs.java create mode 100644 opendaylight/northbound/networkconfiguration/neutron/enunciate.xml create mode 100644 opendaylight/northbound/networkconfiguration/neutron/pom.xml create mode 100644 opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronFloatingIPRequest.java create mode 100644 opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronFloatingIPsNorthbound.java create mode 100644 opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronNBInterfaces.java create mode 100644 opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronNetworkRequest.java create mode 100644 opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronNetworksNorthbound.java create mode 100644 opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronNorthboundRSApplication.java create mode 100644 opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronPortRequest.java create mode 100644 opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronPortsNorthbound.java create mode 100644 opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronRouterRequest.java create mode 100644 opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronRoutersNorthbound.java create mode 100644 opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronSubnetRequest.java create mode 100644 opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronSubnetsNorthbound.java create mode 100644 opendaylight/northbound/networkconfiguration/neutron/src/main/resources/WEB-INF/web.xml create mode 100644 opendaylight/northbound/networkconfiguration/neutron/src/main/resources/org/opendaylight/controller/networkconfig/neutron/northbound/jaxb.properties diff --git a/opendaylight/commons/opendaylight/pom.xml b/opendaylight/commons/opendaylight/pom.xml index 31dd741cfd..3ae9c6ee6c 100644 --- a/opendaylight/commons/opendaylight/pom.xml +++ b/opendaylight/commons/opendaylight/pom.xml @@ -638,6 +638,11 @@ commons-fileupload 1.2.2 + + commons-net + commons-net + 3.0.1 + equinoxSDK381 javax.servlet @@ -1013,5 +1018,20 @@ asm-all 4.1 + + org.eclipse.persistence + org.eclipse.persistence.moxy + 2.5.0 + + + org.eclipse.persistence + org.eclipse.persistence.core + 2.5.0 + + + org.eclipse.persistence + org.eclipse.persistence.antlr + 2.5.0 + diff --git a/opendaylight/distribution/opendaylight/pom.xml b/opendaylight/distribution/opendaylight/pom.xml index 3efd97e2aa..13ac14b5ea 100644 --- a/opendaylight/distribution/opendaylight/pom.xml +++ b/opendaylight/distribution/opendaylight/pom.xml @@ -104,6 +104,11 @@ ../../web/troubleshoot ../../web/topology + + ../../networkconfiguration/neutron + ../../networkconfiguration/neutron/implementation + ../../northbound/networkconfiguration/neutron + ../../northbound/commons ../../northbound/bundlescanner/api diff --git a/opendaylight/networkconfiguration/neutron/implementation/pom.xml b/opendaylight/networkconfiguration/neutron/implementation/pom.xml new file mode 100644 index 0000000000..5aa3c3243a --- /dev/null +++ b/opendaylight/networkconfiguration/neutron/implementation/pom.xml @@ -0,0 +1,81 @@ + + 4.0.0 + + org.opendaylight.controller + commons.opendaylight + 1.4.0-SNAPSHOT + ../../../commons/opendaylight + + + http://nexus.opendaylight.org/content + 1.26.2 + + + + + + opendaylight-release + ${nexusproxy}/repositories/opendaylight.release/ + + + + opendaylight-snapshot + ${nexusproxy}/repositories/opendaylight.snapshot/ + + + + website + ${sitedeploy} + + + org.opendaylight.controller + networkconfig.neutron.implementation + 0.4.0-SNAPSHOT + bundle + + + + org.apache.felix + maven-bundle-plugin + 2.3.6 + true + + + + org.opendaylight.controller.clustering.services, + org.opendaylight.controller.sal.core, + org.opendaylight.controller.sal.utils, + org.apache.felix.dm, + org.apache.commons.net.util, + org.osgi.service.component, + org.opendaylight.controller.networkconfig.neutron, + org.slf4j, + javax.xml.bind.annotation + + + org.opendaylight.controller.networkconfig.neutron.implementation.Activator + + + ${project.basedir}/src/main/resources/META-INF + + + + + + + org.opendaylight.controller + clustering.services + 0.4.0-SNAPSHOT + + + org.opendaylight.controller + networkconfig.neutron + 0.4.0-SNAPSHOT + + + org.opendaylight.controller + sal + 0.5.0-SNAPSHOT + + + diff --git a/opendaylight/networkconfiguration/neutron/implementation/src/main/java/org/opendaylight/controller/networkconfig/neutron/implementation/Activator.java b/opendaylight/networkconfiguration/neutron/implementation/src/main/java/org/opendaylight/controller/networkconfig/neutron/implementation/Activator.java new file mode 100644 index 0000000000..d8d5cc4a0a --- /dev/null +++ b/opendaylight/networkconfiguration/neutron/implementation/src/main/java/org/opendaylight/controller/networkconfig/neutron/implementation/Activator.java @@ -0,0 +1,141 @@ +/* + * Copyright IBM Corporation, 2013. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.networkconfig.neutron.implementation; + +import java.util.Hashtable; +import java.util.Dictionary; +import org.apache.felix.dm.Component; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.opendaylight.controller.clustering.services.IClusterContainerServices; +import org.opendaylight.controller.networkconfig.neutron.INeutronFloatingIPCRUD; +import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD; +import org.opendaylight.controller.networkconfig.neutron.INeutronPortCRUD; +import org.opendaylight.controller.networkconfig.neutron.INeutronRouterCRUD; +import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD; +import org.opendaylight.controller.networkconfig.neutron.implementation.NeutronFloatingIPInterface; +import org.opendaylight.controller.networkconfig.neutron.implementation.NeutronNetworkInterface; +import org.opendaylight.controller.networkconfig.neutron.implementation.NeutronPortInterface; +import org.opendaylight.controller.networkconfig.neutron.implementation.NeutronRouterInterface; +import org.opendaylight.controller.networkconfig.neutron.implementation.NeutronSubnetInterface; +import org.opendaylight.controller.sal.core.ComponentActivatorAbstractBase; + +public class Activator extends ComponentActivatorAbstractBase { + protected static final Logger logger = LoggerFactory + .getLogger(Activator.class); + + /** + * Function called when the activator starts just after some + * initializations are done by the + * ComponentActivatorAbstractBase. + * + */ + public void init() { + + } + + /** + * Function called when the activator stops just before the + * cleanup done by ComponentActivatorAbstractBase + * + */ + public void destroy() { + + } + + /** + * Function that is used to communicate to dependency manager the + * list of known implementations for services inside a container + * + * + * @return An array containing all the CLASS objects that will be + * instantiated in order to get an fully working implementation + * Object + */ + public Object[] getImplementations() { + Object[] res = { NeutronFloatingIPInterface.class, + NeutronRouterInterface.class, + NeutronPortInterface.class, + NeutronSubnetInterface.class, + NeutronNetworkInterface.class }; + return res; + } + + /** + * Function that is called when configuration of the dependencies + * is required. + * + * @param c dependency manager Component object, used for + * configuring the dependencies exported and imported + * @param imp Implementation class that is being configured, + * needed as long as the same routine can configure multiple + * implementations + * @param containerName The containerName being configured, this allow + * also optional per-container different behavior if needed, usually + * should not be the case though. + */ + public void configureInstance(Component c, Object imp, String containerName) { + if (imp.equals(NeutronFloatingIPInterface.class)) { + // export the service + c.setInterface( + new String[] { INeutronFloatingIPCRUD.class.getName() }, null); + Dictionary props = new Hashtable(); + props.put("salListenerName", "neutron"); + c.add(createContainerServiceDependency(containerName) + .setService(IClusterContainerServices.class) + .setCallbacks("setClusterContainerService", + "unsetClusterContainerService").setRequired(true)); + } + if (imp.equals(NeutronRouterInterface.class)) { + // export the service + c.setInterface( + new String[] { INeutronRouterCRUD.class.getName() }, null); + Dictionary props = new Hashtable(); + props.put("salListenerName", "neutron"); + c.add(createContainerServiceDependency(containerName) + .setService(IClusterContainerServices.class) + .setCallbacks("setClusterContainerService", + "unsetClusterContainerService").setRequired(true)); + } + if (imp.equals(NeutronPortInterface.class)) { + // export the service + c.setInterface( + new String[] { INeutronPortCRUD.class.getName() }, null); + Dictionary props = new Hashtable(); + props.put("salListenerName", "neutron"); + c.add(createContainerServiceDependency(containerName) + .setService(IClusterContainerServices.class) + .setCallbacks("setClusterContainerService", + "unsetClusterContainerService").setRequired(true)); + } + if (imp.equals(NeutronSubnetInterface.class)) { + // export the service + c.setInterface( + new String[] { INeutronSubnetCRUD.class.getName() }, null); + Dictionary props = new Hashtable(); + props.put("salListenerName", "neutron"); + c.add(createContainerServiceDependency(containerName) + .setService(IClusterContainerServices.class) + .setCallbacks("setClusterContainerService", + "unsetClusterContainerService").setRequired(true)); + } + if (imp.equals(NeutronNetworkInterface.class)) { + // export the service + c.setInterface( + new String[] { INeutronNetworkCRUD.class.getName() }, null); + Dictionary props = new Hashtable(); + props.put("salListenerName", "neutron"); + c.add(createContainerServiceDependency(containerName) + .setService(IClusterContainerServices.class) + .setCallbacks("setClusterContainerService", + "unsetClusterContainerService").setRequired(true)); + } + } +} diff --git a/opendaylight/networkconfiguration/neutron/implementation/src/main/java/org/opendaylight/controller/networkconfig/neutron/implementation/NeutronFloatingIPInterface.java b/opendaylight/networkconfiguration/neutron/implementation/src/main/java/org/opendaylight/controller/networkconfig/neutron/implementation/NeutronFloatingIPInterface.java new file mode 100644 index 0000000000..7b10756d1c --- /dev/null +++ b/opendaylight/networkconfiguration/neutron/implementation/src/main/java/org/opendaylight/controller/networkconfig/neutron/implementation/NeutronFloatingIPInterface.java @@ -0,0 +1,266 @@ +/* + * Copyright IBM Corporation, 2013. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.networkconfig.neutron.implementation; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Dictionary; +import java.util.EnumSet; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.Map.Entry; +import java.util.concurrent.ConcurrentMap; + +import org.apache.felix.dm.Component; +import org.opendaylight.controller.clustering.services.CacheConfigException; +import org.opendaylight.controller.clustering.services.CacheExistException; +import org.opendaylight.controller.clustering.services.IClusterContainerServices; +import org.opendaylight.controller.clustering.services.IClusterServices; +import org.opendaylight.controller.networkconfig.neutron.INeutronFloatingIPCRUD; +import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD; +import org.opendaylight.controller.networkconfig.neutron.INeutronPortCRUD; +import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD; +import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces; +import org.opendaylight.controller.networkconfig.neutron.NeutronFloatingIP; +import org.opendaylight.controller.networkconfig.neutron.NeutronPort; +import org.opendaylight.controller.networkconfig.neutron.NeutronSubnet; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class NeutronFloatingIPInterface implements INeutronFloatingIPCRUD { + private static final Logger logger = LoggerFactory.getLogger(NeutronFloatingIPInterface.class); + private String containerName = null; + + private IClusterContainerServices clusterContainerService = null; + private ConcurrentMap floatingIPDB; + + // methods needed for creating caches + + void setClusterContainerService(IClusterContainerServices s) { + logger.debug("Cluster Service set"); + this.clusterContainerService = s; + } + + void unsetClusterContainerService(IClusterContainerServices s) { + if (this.clusterContainerService == s) { + logger.debug("Cluster Service removed!"); + this.clusterContainerService = null; + } + } + + @SuppressWarnings("deprecation") + private void allocateCache() { + if (this.clusterContainerService == null) { + logger.error("un-initialized clusterContainerService, can't create cache"); + return; + } + logger.debug("Creating Cache for Neutron FloatingIPs"); + try { + // neutron caches + this.clusterContainerService.createCache("neutronFloatingIPs", + EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL)); + } catch (CacheConfigException cce) { + logger.error("Cache couldn't be created for Neutron - check cache mode"); + } catch (CacheExistException cce) { + logger.error("Cache for Neutron already exists, destroy and recreate"); + } + logger.debug("Cache successfully created for NeutronFloatingIps"); + } + + @SuppressWarnings({ "unchecked", "deprecation" }) + private void retrieveCache() { + if (this.clusterContainerService == null) { + logger.error("un-initialized clusterContainerService, can't retrieve cache"); + return; + } + + logger.debug("Retrieving cache for Neutron FloatingIPs"); + floatingIPDB = (ConcurrentMap) this.clusterContainerService + .getCache("neutronFloatingIPs"); + if (floatingIPDB == null) { + logger.error("Cache couldn't be retrieved for Neutron FloatingIPs"); + } + logger.debug("Cache was successfully retrieved for Neutron FloatingIPs"); + } + + @SuppressWarnings("deprecation") + private void destroyCache() { + if (this.clusterContainerService == null) { + logger.error("un-initialized clusterMger, can't destroy cache"); + return; + } + logger.debug("Destroying Cache for HostTracker"); + this.clusterContainerService.destroyCache("neutronFloatingIPs"); + } + + private void startUp() { + allocateCache(); + retrieveCache(); + } + + /** + * Function called by the dependency manager when all the required + * dependencies are satisfied + * + */ + void init(Component c) { + Dictionary props = c.getServiceProperties(); + if (props != null) { + this.containerName = (String) props.get("containerName"); + logger.debug("Running containerName: {}", this.containerName); + } else { + // In the Global instance case the containerName is empty + this.containerName = ""; + } + startUp(); + } + + /** + * Function called by the dependency manager when at least one dependency + * become unsatisfied or when the component is shutting down because for + * example bundle is being stopped. + * + */ + void destroy() { + destroyCache(); + } + + /** + * Function called by dependency manager after "init ()" is called and after + * the services provided by the class are registered in the service registry + * + */ + void start() { + } + + /** + * Function called by the dependency manager before the services exported by + * the component are unregistered, this will be followed by a "destroy ()" + * calls + * + */ + void stop() { + } + + // this method uses reflection to update an object from it's delta. + + private boolean overwrite(Object target, Object delta) { + Method[] methods = target.getClass().getMethods(); + + for(Method toMethod: methods){ + if(toMethod.getDeclaringClass().equals(target.getClass()) + && toMethod.getName().startsWith("set")){ + + String toName = toMethod.getName(); + String fromName = toName.replace("set", "get"); + + try { + Method fromMethod = delta.getClass().getMethod(fromName); + Object value = fromMethod.invoke(delta, (Object[])null); + if(value != null){ + toMethod.invoke(target, value); + } + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + } + return true; + } + + // IfNBFloatingIPCRUD interface methods + + public boolean floatingIPExists(String uuid) { + return floatingIPDB.containsKey(uuid); + } + + public NeutronFloatingIP getFloatingIP(String uuid) { + if (!floatingIPExists(uuid)) + return null; + return floatingIPDB.get(uuid); + } + + public List getAllFloatingIPs() { + Set allIPs = new HashSet(); + for (Entry entry : floatingIPDB.entrySet()) { + NeutronFloatingIP floatingip = entry.getValue(); + allIPs.add(floatingip); + } + logger.debug("Exiting getAllFloatingIPs, Found {} FloatingIPs", allIPs.size()); + List ans = new ArrayList(); + ans.addAll(allIPs); + return ans; + } + + public boolean addFloatingIP(NeutronFloatingIP input) { + INeutronNetworkCRUD networkCRUD = NeutronCRUDInterfaces.getINeutronNetworkCRUD(this); + INeutronSubnetCRUD subnetCRUD = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this); + INeutronPortCRUD portCRUD = NeutronCRUDInterfaces.getINeutronPortCRUD(this); + + if (floatingIPExists(input.getID())) + return false; + //if floating_ip_address isn't there, allocate from the subnet pool + NeutronSubnet subnet = subnetCRUD.getSubnet(networkCRUD.getNetwork(input.getFloatingNetworkUUID()).getSubnets().get(0)); + if (input.getFloatingIPAddress() == null) + input.setFloatingIPAddress(subnet.getLowAddr()); + subnet.allocateIP(input.getFloatingIPAddress()); + + //if port_id is there, bind port to this floating ip + if (input.getPortUUID() != null) { + NeutronPort port = portCRUD.getPort(input.getPortUUID()); + port.addFloatingIP(input.getFixedIPAddress(), input); + } + + floatingIPDB.putIfAbsent(input.getID(), input); + return true; + } + + public boolean removeFloatingIP(String uuid) { + INeutronNetworkCRUD networkCRUD = NeutronCRUDInterfaces.getINeutronNetworkCRUD(this); + INeutronSubnetCRUD subnetCRUD = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this); + INeutronPortCRUD portCRUD = NeutronCRUDInterfaces.getINeutronPortCRUD(this); + + if (!floatingIPExists(uuid)) + return false; + NeutronFloatingIP floatIP = getFloatingIP(uuid); + //if floating_ip_address isn't there, allocate from the subnet pool + NeutronSubnet subnet = subnetCRUD.getSubnet(networkCRUD.getNetwork(floatIP.getFloatingNetworkUUID()).getSubnets().get(0)); + subnet.releaseIP(floatIP.getFloatingIPAddress()); + if (floatIP.getPortUUID() != null) { + NeutronPort port = portCRUD.getPort(floatIP.getPortUUID()); + port.removeFloatingIP(floatIP.getFixedIPAddress()); + } + floatingIPDB.remove(uuid); + return true; + } + + public boolean updateFloatingIP(String uuid, NeutronFloatingIP delta) { + INeutronPortCRUD portCRUD = NeutronCRUDInterfaces.getINeutronPortCRUD(this); + + if (!floatingIPExists(uuid)) + return false; + NeutronFloatingIP target = floatingIPDB.get(uuid); + if (target.getPortUUID() != null) { + NeutronPort port = portCRUD.getPort(target.getPortUUID()); + port.removeFloatingIP(target.getFixedIPAddress()); + } + + //if port_id is there, bind port to this floating ip + if (delta.getPortUUID() != null) { + NeutronPort port = portCRUD.getPort(delta.getPortUUID()); + port.addFloatingIP(delta.getFixedIPAddress(), delta); + } + + target.setPortUUID(delta.getPortUUID()); + target.setFixedIPAddress(delta.getFixedIPAddress()); + return true; + } +} diff --git a/opendaylight/networkconfiguration/neutron/implementation/src/main/java/org/opendaylight/controller/networkconfig/neutron/implementation/NeutronNetworkInterface.java b/opendaylight/networkconfiguration/neutron/implementation/src/main/java/org/opendaylight/controller/networkconfig/neutron/implementation/NeutronNetworkInterface.java new file mode 100644 index 0000000000..035e6dc4a8 --- /dev/null +++ b/opendaylight/networkconfiguration/neutron/implementation/src/main/java/org/opendaylight/controller/networkconfig/neutron/implementation/NeutronNetworkInterface.java @@ -0,0 +1,227 @@ +/* + * Copyright IBM Corporation, 2013. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.networkconfig.neutron.implementation; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Dictionary; +import java.util.EnumSet; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; +import java.util.Map.Entry; +import java.util.concurrent.ConcurrentMap; + +import org.apache.felix.dm.Component; +import org.opendaylight.controller.clustering.services.CacheConfigException; +import org.opendaylight.controller.clustering.services.CacheExistException; +import org.opendaylight.controller.clustering.services.IClusterContainerServices; +import org.opendaylight.controller.clustering.services.IClusterServices; +import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD; +import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class NeutronNetworkInterface implements INeutronNetworkCRUD { + private static final Logger logger = LoggerFactory.getLogger(NeutronNetworkInterface.class); + private String containerName = null; + + private ConcurrentMap networkDB; + private IClusterContainerServices clusterContainerService = null; + + // methods needed for creating caches + + void setClusterContainerService(IClusterContainerServices s) { + logger.debug("Cluster Service set"); + this.clusterContainerService = s; + } + + void unsetClusterContainerService(IClusterContainerServices s) { + if (this.clusterContainerService == s) { + logger.debug("Cluster Service removed!"); + this.clusterContainerService = null; + } + } + + @SuppressWarnings("deprecation") + private void allocateCache() { + if (this.clusterContainerService == null) { + logger.error("un-initialized clusterContainerService, can't create cache"); + return; + } + logger.debug("Creating Cache for Neutron Networks"); + try { + // neutron caches + this.clusterContainerService.createCache("neutronNetworks", + EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL)); + } catch (CacheConfigException cce) { + logger.error("Cache couldn't be created for Neutron Networks - check cache mode"); + } catch (CacheExistException cce) { + logger.error("Cache for Neutron Networks already exists, destroy and recreate"); + } + logger.debug("Cache successfully created for Neutron Networks"); + } + + @SuppressWarnings({ "unchecked", "deprecation" }) + private void retrieveCache() { + if (this.clusterContainerService == null) { + logger.error("un-initialized clusterContainerService, can't retrieve cache"); + return; + } + logger.debug("Retrieving cache for Neutron Networks"); + networkDB = (ConcurrentMap) this.clusterContainerService.getCache("neutronNetworks"); + if (networkDB == null) { + logger.error("Cache couldn't be retrieved for Neutron Networks"); + } + logger.debug("Cache was successfully retrieved for Neutron Networks"); + } + + private void startUp() { + allocateCache(); + retrieveCache(); + } + + /** + * Function called by the dependency manager when all the required + * dependencies are satisfied + * + */ + void init(Component c) { + Dictionary props = c.getServiceProperties(); + if (props != null) { + this.containerName = (String) props.get("containerName"); + logger.debug("Running containerName: {}", this.containerName); + } else { + // In the Global instance case the containerName is empty + this.containerName = ""; + } + startUp(); + } + + @SuppressWarnings("deprecation") + private void destroyCache() { + if (this.clusterContainerService == null) { + logger.error("un-initialized clusterMger, can't destroy cache"); + return; + } + logger.debug("Destroying Cache for Neutron Networks"); + this.clusterContainerService.destroyCache("Neutron Networks"); + } + + /** + * Function called by the dependency manager when at least one dependency + * become unsatisfied or when the component is shutting down because for + * example bundle is being stopped. + * + */ + void destroy() { + destroyCache(); + } + + /** + * Function called by dependency manager after "init ()" is called and after + * the services provided by the class are registered in the service registry + * + */ + void start() { + } + + /** + * Function called by the dependency manager before the services exported by + * the component are unregistered, this will be followed by a "destroy ()" + * calls + * + */ + void stop() { + } + + // this method uses reflection to update an object from it's delta. + + private boolean overwrite(Object target, Object delta) { + Method[] methods = target.getClass().getMethods(); + + for(Method toMethod: methods){ + if(toMethod.getDeclaringClass().equals(target.getClass()) + && toMethod.getName().startsWith("set")){ + + String toName = toMethod.getName(); + String fromName = toName.replace("set", "get"); + + try { + Method fromMethod = delta.getClass().getMethod(fromName); + Object value = fromMethod.invoke(delta, (Object[])null); + if(value != null){ + toMethod.invoke(target, value); + } + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + } + return true; + } + + // IfNBNetworkCRUD methods + + public boolean networkExists(String uuid) { + return networkDB.containsKey(uuid); + } + + public NeutronNetwork getNetwork(String uuid) { + if (!networkExists(uuid)) + return null; + return networkDB.get(uuid); + } + + public List getAllNetworks() { + Set allNetworks = new HashSet(); + for (Entry entry : networkDB.entrySet()) { + NeutronNetwork network = entry.getValue(); + allNetworks.add(network); + } + logger.debug("Exiting getAllNetworks, Found {} OpenStackNetworks", allNetworks.size()); + List ans = new ArrayList(); + ans.addAll(allNetworks); + return ans; + } + + public boolean addNetwork(NeutronNetwork input) { + if (networkExists(input.getID())) + return false; + networkDB.putIfAbsent(input.getID(), input); + //TODO: add code to find INeutronNetworkAware services and call newtorkCreated on them + return true; + } + + public boolean removeNetwork(String uuid) { + if (!networkExists(uuid)) + return false; + networkDB.remove(uuid); + //TODO: add code to find INeutronNetworkAware services and call newtorkDeleted on them + return true; + } + + public boolean updateNetwork(String uuid, NeutronNetwork delta) { + if (!networkExists(uuid)) + return false; + NeutronNetwork target = networkDB.get(uuid); + return overwrite(target, delta); + } + + public boolean networkInUse(String netUUID) { + if (!networkExists(netUUID)) + return true; + NeutronNetwork target = networkDB.get(netUUID); + if (target.getPortsOnNetwork().size() > 0) + return true; + return false; + } +} diff --git a/opendaylight/networkconfiguration/neutron/implementation/src/main/java/org/opendaylight/controller/networkconfig/neutron/implementation/NeutronPortInterface.java b/opendaylight/networkconfiguration/neutron/implementation/src/main/java/org/opendaylight/controller/networkconfig/neutron/implementation/NeutronPortInterface.java new file mode 100644 index 0000000000..eea19776ec --- /dev/null +++ b/opendaylight/networkconfiguration/neutron/implementation/src/main/java/org/opendaylight/controller/networkconfig/neutron/implementation/NeutronPortInterface.java @@ -0,0 +1,313 @@ +/* + * Copyright IBM Corporation, 2013. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.networkconfig.neutron.implementation; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Dictionary; +import java.util.EnumSet; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; +import java.util.Map.Entry; +import java.util.concurrent.ConcurrentMap; + +import org.apache.felix.dm.Component; +import org.opendaylight.controller.clustering.services.CacheConfigException; +import org.opendaylight.controller.clustering.services.CacheExistException; +import org.opendaylight.controller.clustering.services.IClusterContainerServices; +import org.opendaylight.controller.clustering.services.IClusterServices; +import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD; +import org.opendaylight.controller.networkconfig.neutron.INeutronPortCRUD; +import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD; +import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces; +import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork; +import org.opendaylight.controller.networkconfig.neutron.NeutronPort; +import org.opendaylight.controller.networkconfig.neutron.NeutronSubnet; +import org.opendaylight.controller.networkconfig.neutron.Neutron_IPs; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class NeutronPortInterface implements INeutronPortCRUD { + private static final Logger logger = LoggerFactory.getLogger(NeutronPortInterface.class); + private String containerName = null; + + private IClusterContainerServices clusterContainerService = null; + private ConcurrentMap portDB; + + // methods needed for creating caches + + void setClusterContainerService(IClusterContainerServices s) { + logger.debug("Cluster Service set"); + this.clusterContainerService = s; + } + + void unsetClusterContainerService(IClusterContainerServices s) { + if (this.clusterContainerService == s) { + logger.debug("Cluster Service removed!"); + this.clusterContainerService = null; + } + } + + @SuppressWarnings("deprecation") + private void allocateCache() { + if (this.clusterContainerService == null) { + logger.error("un-initialized clusterContainerService, can't create cache"); + return; + } + logger.debug("Creating Cache for OpenDOVE"); + try { + // neutron caches + this.clusterContainerService.createCache("neutronPorts", + EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL)); + } catch (CacheConfigException cce) { + logger.error("Cache couldn't be created for OpenDOVE - check cache mode"); + } catch (CacheExistException cce) { + logger.error("Cache for OpenDOVE already exists, destroy and recreate"); + } + logger.debug("Cache successfully created for OpenDOVE"); + } + + @SuppressWarnings({ "unchecked", "deprecation" }) + private void retrieveCache() { + if (this.clusterContainerService == null) { + logger.error("un-initialized clusterContainerService, can't retrieve cache"); + return; + } + + logger.debug("Retrieving cache for Neutron Ports"); + portDB = (ConcurrentMap) this.clusterContainerService + .getCache("neutronPorts"); + if (portDB == null) { + logger.error("Cache couldn't be retrieved for Neutron Ports"); + } + logger.debug("Cache was successfully retrieved for Neutron Ports"); + } + + @SuppressWarnings("deprecation") + private void destroyCache() { + if (this.clusterContainerService == null) { + logger.error("un-initialized clusterMger, can't destroy cache"); + return; + } + logger.debug("Destroying Cache for HostTracker"); + this.clusterContainerService.destroyCache("neutronPorts"); + } + + private void startUp() { + allocateCache(); + retrieveCache(); + } + + /** + * Function called by the dependency manager when all the required + * dependencies are satisfied + * + */ + void init(Component c) { + Dictionary props = c.getServiceProperties(); + if (props != null) { + this.containerName = (String) props.get("containerName"); + logger.debug("Running containerName: {}", this.containerName); + } else { + // In the Global instance case the containerName is empty + this.containerName = ""; + } + startUp(); + } + + /** + * Function called by the dependency manager when at least one dependency + * become unsatisfied or when the component is shutting down because for + * example bundle is being stopped. + * + */ + void destroy() { + destroyCache(); + } + + /** + * Function called by dependency manager after "init ()" is called and after + * the services provided by the class are registered in the service registry + * + */ + void start() { + } + + /** + * Function called by the dependency manager before the services exported by + * the component are unregistered, this will be followed by a "destroy ()" + * calls + * + */ + void stop() { + } + + // this method uses reflection to update an object from it's delta. + + private boolean overwrite(Object target, Object delta) { + Method[] methods = target.getClass().getMethods(); + + for(Method toMethod: methods){ + if(toMethod.getDeclaringClass().equals(target.getClass()) + && toMethod.getName().startsWith("set")){ + + String toName = toMethod.getName(); + String fromName = toName.replace("set", "get"); + + try { + Method fromMethod = delta.getClass().getMethod(fromName); + Object value = fromMethod.invoke(delta, (Object[])null); + if(value != null){ + toMethod.invoke(target, value); + } + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + } + return true; + } + + // IfNBPortCRUD methods + + public boolean portExists(String uuid) { + return portDB.containsKey(uuid); + } + + public NeutronPort getPort(String uuid) { + if (!portExists(uuid)) + return null; + return portDB.get(uuid); + } + + public List getAllPorts() { + Set allPorts = new HashSet(); + for (Entry entry : portDB.entrySet()) { + NeutronPort port = entry.getValue(); + allPorts.add(port); + } + logger.debug("Exiting getAllPorts, Found {} OpenStackPorts", allPorts.size()); + List ans = new ArrayList(); + ans.addAll(allPorts); + return ans; + } + + public boolean addPort(NeutronPort input) { + if (portExists(input.getID())) + return false; + portDB.putIfAbsent(input.getID(), input); + // if there are no fixed IPs, allocate one for each subnet in the network + INeutronSubnetCRUD systemCRUD = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this); + if (input.getFixedIPs().size() == 0) { + List list = input.getFixedIPs(); + Iterator subnetIterator = systemCRUD.getAllSubnets().iterator(); + while (subnetIterator.hasNext()) { + NeutronSubnet subnet = subnetIterator.next(); + if (subnet.getNetworkUUID().equals(input.getNetworkUUID())) + list.add(new Neutron_IPs(subnet.getID())); + } + } + Iterator fixedIPIterator = input.getFixedIPs().iterator(); + while (fixedIPIterator.hasNext()) { + Neutron_IPs ip = fixedIPIterator.next(); + NeutronSubnet subnet = systemCRUD.getSubnet(ip.getSubnetUUID()); + if (ip.getIpAddress() == null) + ip.setIpAddress(subnet.getLowAddr()); + if (!ip.getIpAddress().equals(subnet.getGatewayIP())) + subnet.allocateIP(ip.getIpAddress()); + else + subnet.setGatewayIPAllocated(); + subnet.addPort(input); + } + INeutronNetworkCRUD networkIf = NeutronCRUDInterfaces.getINeutronNetworkCRUD(this); + + NeutronNetwork network = networkIf.getNetwork(input.getNetworkUUID()); + network.addPort(input); + return true; + } + + public boolean removePort(String uuid) { + if (!portExists(uuid)) + return false; + NeutronPort port = getPort(uuid); + portDB.remove(uuid); + INeutronNetworkCRUD networkCRUD = NeutronCRUDInterfaces.getINeutronNetworkCRUD(this); + INeutronSubnetCRUD systemCRUD = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this); + + NeutronNetwork network = networkCRUD.getNetwork(port.getNetworkUUID()); + network.removePort(port); + Iterator fixedIPIterator = port.getFixedIPs().iterator(); + while (fixedIPIterator.hasNext()) { + Neutron_IPs ip = fixedIPIterator.next(); + NeutronSubnet subnet = systemCRUD.getSubnet(ip.getSubnetUUID()); + if (!ip.getIpAddress().equals(subnet.getGatewayIP())) + subnet.releaseIP(ip.getIpAddress()); + else + subnet.resetGatewayIPAllocated(); + subnet.removePort(port); + } + return true; + } + + public boolean updatePort(String uuid, NeutronPort delta) { + if (!portExists(uuid)) + return false; + NeutronPort target = portDB.get(uuid); + // remove old Fixed_IPs + NeutronPort port = getPort(uuid); + INeutronSubnetCRUD systemCRUD = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this); + Iterator fixedIPIterator = port.getFixedIPs().iterator(); + while (fixedIPIterator.hasNext()) { + Neutron_IPs ip = fixedIPIterator.next(); + NeutronSubnet subnet = systemCRUD.getSubnet(ip.getSubnetUUID()); + subnet.releaseIP(ip.getIpAddress()); + } + + // allocate new Fixed_IPs + fixedIPIterator = delta.getFixedIPs().iterator(); + while (fixedIPIterator.hasNext()) { + Neutron_IPs ip = fixedIPIterator.next(); + NeutronSubnet subnet = systemCRUD.getSubnet(ip.getSubnetUUID()); + if (ip.getIpAddress() == null) + ip.setIpAddress(subnet.getLowAddr()); + subnet.allocateIP(ip.getIpAddress()); + } + return overwrite(target, delta); + } + + public boolean macInUse(String macAddress) { + List ports = getAllPorts(); + Iterator portIterator = ports.iterator(); + while (portIterator.hasNext()) { + NeutronPort port = portIterator.next(); + if (macAddress.equalsIgnoreCase(port.getMacAddress())) + return true; + } + return false; + } + + public NeutronPort getGatewayPort(String subnetUUID) { + INeutronSubnetCRUD systemCRUD = NeutronCRUDInterfaces.getINeutronSubnetCRUD(this); + NeutronSubnet subnet = systemCRUD.getSubnet(subnetUUID); + Iterator portIterator = getAllPorts().iterator(); + while (portIterator.hasNext()) { + NeutronPort port = portIterator.next(); + List fixedIPs = port.getFixedIPs(); + if (fixedIPs.size() == 1) { + if (subnet.getGatewayIP().equals(fixedIPs.get(0).getIpAddress())) + return port; + } + } + return null; + } + +} diff --git a/opendaylight/networkconfiguration/neutron/implementation/src/main/java/org/opendaylight/controller/networkconfig/neutron/implementation/NeutronRouterInterface.java b/opendaylight/networkconfiguration/neutron/implementation/src/main/java/org/opendaylight/controller/networkconfig/neutron/implementation/NeutronRouterInterface.java new file mode 100644 index 0000000000..0a7afa562c --- /dev/null +++ b/opendaylight/networkconfiguration/neutron/implementation/src/main/java/org/opendaylight/controller/networkconfig/neutron/implementation/NeutronRouterInterface.java @@ -0,0 +1,224 @@ +/* + * Copyright IBM Corporation, 2013. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.networkconfig.neutron.implementation; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Dictionary; +import java.util.EnumSet; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.Map.Entry; +import java.util.concurrent.ConcurrentMap; + +import org.apache.felix.dm.Component; +import org.opendaylight.controller.clustering.services.CacheConfigException; +import org.opendaylight.controller.clustering.services.CacheExistException; +import org.opendaylight.controller.clustering.services.IClusterContainerServices; +import org.opendaylight.controller.clustering.services.IClusterServices; +import org.opendaylight.controller.networkconfig.neutron.INeutronRouterCRUD; +import org.opendaylight.controller.networkconfig.neutron.NeutronRouter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class NeutronRouterInterface implements INeutronRouterCRUD { + private static final Logger logger = LoggerFactory.getLogger(NeutronRouterInterface.class); + private String containerName = null; + + private IClusterContainerServices clusterContainerService = null; + private ConcurrentMap routerDB; + // methods needed for creating caches + + void setClusterContainerService(IClusterContainerServices s) { + logger.debug("Cluster Service set"); + this.clusterContainerService = s; + } + + void unsetClusterContainerService(IClusterContainerServices s) { + if (this.clusterContainerService == s) { + logger.debug("Cluster Service removed!"); + this.clusterContainerService = null; + } + } + + @SuppressWarnings("deprecation") + private void allocateCache() { + if (this.clusterContainerService == null) { + logger.error("un-initialized clusterContainerService, can't create cache"); + return; + } + logger.debug("Creating Cache for Neutron Routers"); + try { + // neutron caches + this.clusterContainerService.createCache("neutronRouters", + EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL)); + } catch (CacheConfigException cce) { + logger.error("Cache couldn't be created for Neutron Routers - check cache mode"); + } catch (CacheExistException cce) { + logger.error("Cache for Neutron Routers already exists, destroy and recreate"); + } + logger.debug("Cache successfully created for Neutron Routers"); + } + + @SuppressWarnings({ "unchecked", "deprecation" }) + private void retrieveCache() { + if (this.clusterContainerService == null) { + logger.error("un-initialized clusterContainerService, can't retrieve cache"); + return; + } + + logger.debug("Retrieving cache for Neutron Routers"); + routerDB = (ConcurrentMap) this.clusterContainerService + .getCache("neutronRouters"); + if (routerDB == null) { + logger.error("Cache couldn't be retrieved for Neutron Routers"); + } + logger.debug("Cache was successfully retrieved for Neutron Routers"); + } + + @SuppressWarnings("deprecation") + private void destroyCache() { + if (this.clusterContainerService == null) { + logger.error("un-initialized clusterMger, can't destroy cache"); + return; + } + logger.debug("Destroying Cache for HostTracker"); + this.clusterContainerService.destroyCache("neutronRouters"); + } + + private void startUp() { + allocateCache(); + retrieveCache(); + } + + /** + * Function called by the dependency manager when all the required + * dependencies are satisfied + * + */ + void init(Component c) { + Dictionary props = c.getServiceProperties(); + if (props != null) { + this.containerName = (String) props.get("containerName"); + logger.debug("Running containerName: {}", this.containerName); + } else { + // In the Global instance case the containerName is empty + this.containerName = ""; + } + startUp(); + } + + /** + * Function called by the dependency manager when at least one dependency + * become unsatisfied or when the component is shutting down because for + * example bundle is being stopped. + * + */ + void destroy() { + destroyCache(); + } + + /** + * Function called by dependency manager after "init ()" is called and after + * the services provided by the class are registered in the service registry + * + */ + void start() { + } + + /** + * Function called by the dependency manager before the services exported by + * the component are unregistered, this will be followed by a "destroy ()" + * calls + * + */ + void stop() { + } + + // this method uses reflection to update an object from it's delta. + + private boolean overwrite(Object target, Object delta) { + Method[] methods = target.getClass().getMethods(); + + for(Method toMethod: methods){ + if(toMethod.getDeclaringClass().equals(target.getClass()) + && toMethod.getName().startsWith("set")){ + + String toName = toMethod.getName(); + String fromName = toName.replace("set", "get"); + + try { + Method fromMethod = delta.getClass().getMethod(fromName); + Object value = fromMethod.invoke(delta, (Object[])null); + if(value != null){ + toMethod.invoke(target, value); + } + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + } + return true; + } + + + // IfNBRouterCRUD Interface methods + + public boolean routerExists(String uuid) { + return routerDB.containsKey(uuid); + } + + public NeutronRouter getRouter(String uuid) { + if (!routerExists(uuid)) + return null; + return routerDB.get(uuid); + } + + public List getAllRouters() { + Set allRouters = new HashSet(); + for (Entry entry : routerDB.entrySet()) { + NeutronRouter router = entry.getValue(); + allRouters.add(router); + } + logger.debug("Exiting getAllRouters, Found {} Routers", allRouters.size()); + List ans = new ArrayList(); + ans.addAll(allRouters); + return ans; + } + + public boolean addRouter(NeutronRouter input) { + if (routerExists(input.getID())) + return false; + routerDB.putIfAbsent(input.getID(), input); + return true; + } + + public boolean removeRouter(String uuid) { + if (!routerExists(uuid)) + return false; + routerDB.remove(uuid); + return true; + } + + public boolean updateRouter(String uuid, NeutronRouter delta) { + if (!routerExists(uuid)) + return false; + NeutronRouter target = routerDB.get(uuid); + return overwrite(target, delta); + } + + public boolean routerInUse(String routerUUID) { + if (!routerExists(routerUUID)) + return true; + NeutronRouter target = routerDB.get(routerUUID); + return (target.getInterfaces().size() > 0); + } +} diff --git a/opendaylight/networkconfiguration/neutron/implementation/src/main/java/org/opendaylight/controller/networkconfig/neutron/implementation/NeutronSubnetInterface.java b/opendaylight/networkconfiguration/neutron/implementation/src/main/java/org/opendaylight/controller/networkconfig/neutron/implementation/NeutronSubnetInterface.java new file mode 100644 index 0000000000..0fc333723a --- /dev/null +++ b/opendaylight/networkconfiguration/neutron/implementation/src/main/java/org/opendaylight/controller/networkconfig/neutron/implementation/NeutronSubnetInterface.java @@ -0,0 +1,238 @@ +/* + * Copyright IBM Corporation, 2013. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.networkconfig.neutron.implementation; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Dictionary; +import java.util.EnumSet; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.Map.Entry; +import java.util.concurrent.ConcurrentMap; + +import org.apache.felix.dm.Component; +import org.opendaylight.controller.clustering.services.CacheConfigException; +import org.opendaylight.controller.clustering.services.CacheExistException; +import org.opendaylight.controller.clustering.services.IClusterContainerServices; +import org.opendaylight.controller.clustering.services.IClusterServices; +import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD; +import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD; +import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces; +import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork; +import org.opendaylight.controller.networkconfig.neutron.NeutronSubnet; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class NeutronSubnetInterface implements INeutronSubnetCRUD { + private static final Logger logger = LoggerFactory.getLogger(NeutronSubnetInterface.class); + private String containerName = null; + + private IClusterContainerServices clusterContainerService = null; + private ConcurrentMap subnetDB; + + // methods needed for creating caches + + void setClusterContainerService(IClusterContainerServices s) { + logger.debug("Cluster Service set"); + this.clusterContainerService = s; + } + + void unsetClusterContainerService(IClusterContainerServices s) { + if (this.clusterContainerService == s) { + logger.debug("Cluster Service removed!"); + this.clusterContainerService = null; + } + } + + @SuppressWarnings("deprecation") + private void allocateCache() { + if (this.clusterContainerService == null) { + logger.error("un-initialized clusterContainerService, can't create cache"); + return; + } + logger.debug("Creating Cache for Neutron Subnets"); + try { + // neutron caches + this.clusterContainerService.createCache("neutronSubnets", + EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL)); + } catch (CacheConfigException cce) { + logger.error("Cache couldn't be created for Neutron Subnets - check cache mode"); + } catch (CacheExistException cce) { + logger.error("Cache for Neutron Subnets already exists, destroy and recreate"); + } + logger.debug("Cache successfully created for Neutron Subnets"); + } + + @SuppressWarnings({ "unchecked", "deprecation" }) + private void retrieveCache() { + if (this.clusterContainerService == null) { + logger.error("un-initialized clusterContainerService, can't retrieve cache"); + return; + } + + logger.debug("Retrieving cache for Neutron Subnets"); + subnetDB = (ConcurrentMap) this.clusterContainerService + .getCache("neutronSubnets"); + if (subnetDB == null) { + logger.error("Cache couldn't be retrieved for Neutron Subnets"); + } + logger.debug("Cache was successfully retrieved for Neutron Subnets"); + } + + @SuppressWarnings("deprecation") + private void destroyCache() { + if (this.clusterContainerService == null) { + logger.error("un-initialized clusterMger, can't destroy cache"); + return; + } + logger.debug("Destroying Cache for HostTracker"); + this.clusterContainerService.destroyCache("neutronSubnets"); + } + + private void startUp() { + allocateCache(); + retrieveCache(); + } + + /** + * Function called by the dependency manager when all the required + * dependencies are satisfied + * + */ + void init(Component c) { + Dictionary props = c.getServiceProperties(); + if (props != null) { + this.containerName = (String) props.get("containerName"); + logger.debug("Running containerName: {}", this.containerName); + } else { + // In the Global instance case the containerName is empty + this.containerName = ""; + } + startUp(); + } + + /** + * Function called by the dependency manager when at least one dependency + * become unsatisfied or when the component is shutting down because for + * example bundle is being stopped. + * + */ + void destroy() { + destroyCache(); + } + + /** + * Function called by dependency manager after "init ()" is called and after + * the services provided by the class are registered in the service registry + * + */ + void start() { + } + + /** + * Function called by the dependency manager before the services exported by + * the component are unregistered, this will be followed by a "destroy ()" + * calls + * + */ + void stop() { + } + + // this method uses reflection to update an object from it's delta. + + private boolean overwrite(Object target, Object delta) { + Method[] methods = target.getClass().getMethods(); + + for(Method toMethod: methods){ + if(toMethod.getDeclaringClass().equals(target.getClass()) + && toMethod.getName().startsWith("set")){ + + String toName = toMethod.getName(); + String fromName = toName.replace("set", "get"); + + try { + Method fromMethod = delta.getClass().getMethod(fromName); + Object value = fromMethod.invoke(delta, (Object[])null); + if(value != null){ + toMethod.invoke(target, value); + } + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + } + return true; + } + + + // IfNBSubnetCRUD methods + + public boolean subnetExists(String uuid) { + return subnetDB.containsKey(uuid); + } + + public NeutronSubnet getSubnet(String uuid) { + if (!subnetExists(uuid)) + return null; + return subnetDB.get(uuid); + } + + public List getAllSubnets() { + Set allSubnets = new HashSet(); + for (Entry entry : subnetDB.entrySet()) { + NeutronSubnet subnet = entry.getValue(); + allSubnets.add(subnet); + } + logger.debug("Exiting getAllSubnets, Found {} OpenStackSubnets", allSubnets.size()); + List ans = new ArrayList(); + ans.addAll(allSubnets); + return ans; + } + + public boolean addSubnet(NeutronSubnet input) { + String id = input.getID(); + if (subnetExists(id)) + return false; + subnetDB.putIfAbsent(id, input); + INeutronNetworkCRUD networkIf = NeutronCRUDInterfaces.getINeutronNetworkCRUD(this); + + NeutronNetwork targetNet = networkIf.getNetwork(input.getNetworkUUID()); + targetNet.addSubnet(id); + return true; + } + + public boolean removeSubnet(String uuid) { + if (!subnetExists(uuid)) + return false; + NeutronSubnet target = subnetDB.get(uuid); + INeutronNetworkCRUD networkIf = NeutronCRUDInterfaces.getINeutronNetworkCRUD(this); + + NeutronNetwork targetNet = networkIf.getNetwork(target.getNetworkUUID()); + targetNet.removeSubnet(uuid); + subnetDB.remove(uuid); + return true; + } + + public boolean updateSubnet(String uuid, NeutronSubnet delta) { + if (!subnetExists(uuid)) + return false; + NeutronSubnet target = subnetDB.get(uuid); + return overwrite(target, delta); + } + + public boolean subnetInUse(String subnetUUID) { + if (!subnetExists(subnetUUID)) + return true; + NeutronSubnet target = subnetDB.get(subnetUUID); + return (target.getPortsInSubnet().size() > 0); + } +} diff --git a/opendaylight/networkconfiguration/neutron/pom.xml b/opendaylight/networkconfiguration/neutron/pom.xml new file mode 100644 index 0000000000..a905ebfa30 --- /dev/null +++ b/opendaylight/networkconfiguration/neutron/pom.xml @@ -0,0 +1,71 @@ + + 4.0.0 + + org.opendaylight.controller + commons.opendaylight + 1.4.0-SNAPSHOT + ../../commons/opendaylight + + + http://nexus.opendaylight.org/content + 1.26.2 + + + + + opendaylight-release + ${nexusproxy}/repositories/opendaylight.release/ + + + + opendaylight-snapshot + ${nexusproxy}/repositories/opendaylight.snapshot/ + + + + website + ${sitedeploy} + + + org.opendaylight.controller + networkconfig.neutron + 0.4.0-SNAPSHOT + bundle + + + + org.apache.felix + maven-bundle-plugin + 2.3.6 + true + + + + org.opendaylight.controller.clustering.services, + org.opendaylight.controller.sal.core, + org.opendaylight.controller.sal.utils, + org.apache.felix.dm, + org.apache.commons.net.util, + org.osgi.service.component, + org.slf4j, + javax.xml.bind.annotation + + + ${project.basedir}/src/main/resources/META-INF + + + + + + + org.opendaylight.controller + clustering.services + 0.4.0-SNAPSHOT + + + org.opendaylight.controller + sal + 0.5.0-SNAPSHOT + + + diff --git a/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronFloatingIPAware.java b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronFloatingIPAware.java new file mode 100644 index 0000000000..05d50be818 --- /dev/null +++ b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronFloatingIPAware.java @@ -0,0 +1,83 @@ +/* + * Copyright IBM Corporation, 2013. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.networkconfig.neutron; + +/** + * This interface defines the methods a service that wishes to be aware of Neutron FloatingIPs needs to implement + * + */ + +public interface INeutronFloatingIPAware { + + /** + * Services provide this interface method to indicate if the specified floatingIP can be created + * + * @param floatingIP + * instance of proposed new Neutron FloatingIP object + * @return integer + * the return value is understood to be a HTTP status code. A return value outside of 200 through 299 + * results in the create operation being interrupted and the returned status value reflected in the + * HTTP response. + */ + public int canCreateFloatingIP(NeutronFloatingIP floatingIP); + + /** + * Services provide this interface method for taking action after a floatingIP has been created + * + * @param floatingIP + * instance of new Neutron FloatingIP object + * @return void + */ + public void neutronFloatingIPCreated(NeutronFloatingIP floatingIP); + + /** + * Services provide this interface method to indicate if the specified floatingIP can be changed using the specified + * delta + * + * @param delta + * updates to the floatingIP object using patch semantics + * @param floatingIP + * instance of the Neutron FloatingIP object to be updated + * @return integer + * the return value is understood to be a HTTP status code. A return value outside of 200 through 299 + * results in the update operation being interrupted and the returned status value reflected in the + * HTTP response. + */ + public int canUpdateFloatingIP(NeutronFloatingIP delta, NeutronFloatingIP original); + + /** + * Services provide this interface method for taking action after a floatingIP has been updated + * + * @param floatingIP + * instance of modified Neutron FloatingIP object + * @return void + */ + public void neutronFloatingIPUpdated(NeutronFloatingIP floatingIP); + + /** + * Services provide this interface method to indicate if the specified floatingIP can be deleted + * + * @param floatingIP + * instance of the Neutron FloatingIP object to be deleted + * @return integer + * the return value is understood to be a HTTP status code. A return value outside of 200 through 299 + * results in the delete operation being interrupted and the returned status value reflected in the + * HTTP response. + */ + public int canDeleteFloatingIP(NeutronFloatingIP floatingIP); + + /** + * Services provide this interface method for taking action after a floatingIP has been deleted + * + * @param floatingIP + * instance of deleted Neutron FloatingIP object + * @return void + */ + public void neutronFloatingIPDeleted(NeutronFloatingIP floatingIP); +} diff --git a/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronFloatingIPCRUD.java b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronFloatingIPCRUD.java new file mode 100644 index 0000000000..7443deec6e --- /dev/null +++ b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronFloatingIPCRUD.java @@ -0,0 +1,83 @@ +/* + * Copyright IBM Corporation, 2013. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.networkconfig.neutron; + +import java.util.List; + +/** + * This interface defines the methods for CRUD of NB FloatingIP objects + * + */ + +public interface INeutronFloatingIPCRUD { + /** + * Applications call this interface method to determine if a particular + * FloatingIP object exists + * + * @param uuid + * UUID of the FloatingIP object + * @return boolean + */ + + public boolean floatingIPExists(String uuid); + + /** + * Applications call this interface method to return if a particular + * FloatingIP object exists + * + * @param uuid + * UUID of the FloatingIP object + * @return {@link org.opendaylight.controller.networkconfig.neutron.NeutronFloatingIP.OpenStackFloatingIPs} + * OpenStack FloatingIP class + */ + + public NeutronFloatingIP getFloatingIP(String uuid); + + /** + * Applications call this interface method to return all FloatingIP objects + * + * @return a Set of OpenStackFloatingIPs objects + */ + + public List getAllFloatingIPs(); + + /** + * Applications call this interface method to add a FloatingIP object to the + * concurrent map + * + * @param input + * OpenStackFloatingIP object + * @return boolean on whether the object was added or not + */ + + public boolean addFloatingIP(NeutronFloatingIP input); + + /** + * Applications call this interface method to remove a FloatingIP object to the + * concurrent map + * + * @param uuid + * identifier for the FloatingIP object + * @return boolean on whether the object was removed or not + */ + + public boolean removeFloatingIP(String uuid); + + /** + * Applications call this interface method to edit a FloatingIP object + * + * @param uuid + * identifier of the FloatingIP object + * @param delta + * OpenStackFloatingIP object containing changes to apply + * @return boolean on whether the object was updated or not + */ + + public boolean updateFloatingIP(String uuid, NeutronFloatingIP delta); +} diff --git a/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronNetworkAware.java b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronNetworkAware.java new file mode 100644 index 0000000000..dc6df25ab7 --- /dev/null +++ b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronNetworkAware.java @@ -0,0 +1,83 @@ +/* + * Copyright IBM Corporation, 2013. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.networkconfig.neutron; + +/** + * This interface defines the methods a service that wishes to be aware of Neutron Networks needs to implement + * + */ + +public interface INeutronNetworkAware { + + /** + * Services provide this interface method to indicate if the specified network can be created + * + * @param network + * instance of proposed new Neutron Network object + * @return integer + * the return value is understood to be a HTTP status code. A return value outside of 200 through 299 + * results in the create operation being interrupted and the returned status value reflected in the + * HTTP response. + */ + public int canCreateNetwork(NeutronNetwork network); + + /** + * Services provide this interface method for taking action after a network has been created + * + * @param network + * instance of new Neutron Network object + * @return void + */ + public void neutronNetworkCreated(NeutronNetwork network); + + /** + * Services provide this interface method to indicate if the specified network can be changed using the specified + * delta + * + * @param delta + * updates to the network object using patch semantics + * @param network + * instance of the Neutron Network object to be updated + * @return integer + * the return value is understood to be a HTTP status code. A return value outside of 200 through 299 + * results in the update operation being interrupted and the returned status value reflected in the + * HTTP response. + */ + public int canUpdateNetwork(NeutronNetwork delta, NeutronNetwork original); + + /** + * Services provide this interface method for taking action after a network has been updated + * + * @param network + * instance of modified Neutron Network object + * @return void + */ + public void neutronNetworkUpdated(NeutronNetwork network); + + /** + * Services provide this interface method to indicate if the specified network can be deleted + * + * @param network + * instance of the Neutron Network object to be deleted + * @return integer + * the return value is understood to be a HTTP status code. A return value outside of 200 through 299 + * results in the delete operation being interrupted and the returned status value reflected in the + * HTTP response. + */ + public int canDeleteNetwork(NeutronNetwork network); + + /** + * Services provide this interface method for taking action after a network has been deleted + * + * @param network + * instance of deleted Neutron Network object + * @return void + */ + public void neutronNetworkDeleted(NeutronNetwork network); +} diff --git a/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronNetworkCRUD.java b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronNetworkCRUD.java new file mode 100644 index 0000000000..248153105c --- /dev/null +++ b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronNetworkCRUD.java @@ -0,0 +1,95 @@ +/* + * Copyright IBM Corporation, 2013. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.networkconfig.neutron; + +import java.util.List; + +/** + * This interface defines the methods for CRUD of NB network objects + * + */ + +public interface INeutronNetworkCRUD { + /** + * Applications call this interface method to determine if a particular + * Network object exists + * + * @param uuid + * UUID of the Network object + * @return boolean + */ + + public boolean networkExists(String uuid); + + /** + * Applications call this interface method to return if a particular + * Network object exists + * + * @param uuid + * UUID of the Network object + * @return {@link org.opendaylight.controller.networkconfig.neutron.NeutronNetwork.OpenStackNetworks} + * OpenStack Network class + */ + + public NeutronNetwork getNetwork(String uuid); + + /** + * Applications call this interface method to return all Network objects + * + * @return List of OpenStackNetworks objects + */ + + public List getAllNetworks(); + + /** + * Applications call this interface method to add a Network object to the + * concurrent map + * + * @param input + * OpenStackNetwork object + * @return boolean on whether the object was added or not + */ + + public boolean addNetwork(NeutronNetwork input); + + /** + * Applications call this interface method to remove a Network object to the + * concurrent map + * + * @param uuid + * identifier for the network object + * @return boolean on whether the object was removed or not + */ + + public boolean removeNetwork(String uuid); + + /** + * Applications call this interface method to edit a Network object + * + * @param uuid + * identifier of the network object + * @param delta + * OpenStackNetwork object containing changes to apply + * @return boolean on whether the object was updated or not + */ + + public boolean updateNetwork(String uuid, NeutronNetwork delta); + + /** + * Applications call this interface method to determine if a Network object + * is use + * + * @param netUUID + * identifier of the network object + * + * @return boolean on whether the network is in use or not + */ + + public boolean networkInUse(String netUUID); +} diff --git a/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronPortAware.java b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronPortAware.java new file mode 100644 index 0000000000..36ed4ffb39 --- /dev/null +++ b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronPortAware.java @@ -0,0 +1,83 @@ +/* + * Copyright IBM Corporation, 2013. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.networkconfig.neutron; + +/** + * This interface defines the methods a service that wishes to be aware of Neutron Ports needs to implement + * + */ + +public interface INeutronPortAware { + + /** + * Services provide this interface method to indicate if the specified port can be created + * + * @param port + * instance of proposed new Neutron Port object + * @return integer + * the return value is understood to be a HTTP status code. A return value outside of 200 through 299 + * results in the create operation being interrupted and the returned status value reflected in the + * HTTP response. + */ + public int canCreatePort(NeutronPort port); + + /** + * Services provide this interface method for taking action after a port has been created + * + * @param port + * instance of new Neutron Port object + * @return void + */ + public void neutronPortCreated(NeutronPort port); + + /** + * Services provide this interface method to indicate if the specified port can be changed using the specified + * delta + * + * @param delta + * updates to the port object using patch semantics + * @param port + * instance of the Neutron Port object to be updated + * @return integer + * the return value is understood to be a HTTP status code. A return value outside of 200 through 299 + * results in the update operation being interrupted and the returned status value reflected in the + * HTTP response. + */ + public int canUpdatePort(NeutronPort delta, NeutronPort original); + + /** + * Services provide this interface method for taking action after a port has been updated + * + * @param port + * instance of modified Neutron Port object + * @return void + */ + public void neutronPortUpdated(NeutronPort port); + + /** + * Services provide this interface method to indicate if the specified port can be deleted + * + * @param port + * instance of the Neutron Port object to be deleted + * @return integer + * the return value is understood to be a HTTP status code. A return value outside of 200 through 299 + * results in the delete operation being interrupted and the returned status value reflected in the + * HTTP response. + */ + public int canDeletePort(NeutronPort port); + + /** + * Services provide this interface method for taking action after a port has been deleted + * + * @param port + * instance of deleted Port Network object + * @return void + */ + public void neutronPortDeleted(NeutronPort port); +} diff --git a/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronPortCRUD.java b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronPortCRUD.java new file mode 100644 index 0000000000..681e925377 --- /dev/null +++ b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronPortCRUD.java @@ -0,0 +1,105 @@ +/* + * Copyright IBM Corporation, 2013. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.networkconfig.neutron; + +import java.util.List; + +/** + * This interface defines the methods for CRUD of NB Port objects + * + */ + +public interface INeutronPortCRUD { + /** + * Applications call this interface method to determine if a particular + * Port object exists + * + * @param uuid + * UUID of the Port object + * @return boolean + */ + + public boolean portExists(String uuid); + + /** + * Applications call this interface method to return if a particular + * Port object exists + * + * @param uuid + * UUID of the Port object + * @return {@link org.opendaylight.controller.networkconfig.neutron.NeutronPort.OpenStackPorts} + * OpenStack Port class + */ + + public NeutronPort getPort(String uuid); + + /** + * Applications call this interface method to return all Port objects + * + * @return List of OpenStackPorts objects + */ + + public List getAllPorts(); + + /** + * Applications call this interface method to add a Port object to the + * concurrent map + * + * @param input + * OpenStackPort object + * @return boolean on whether the object was added or not + */ + + public boolean addPort(NeutronPort input); + + /** + * Applications call this interface method to remove a Port object to the + * concurrent map + * + * @param uuid + * identifier for the Port object + * @return boolean on whether the object was removed or not + */ + + public boolean removePort(String uuid); + + /** + * Applications call this interface method to edit a Port object + * + * @param uuid + * identifier of the Port object + * @param delta + * OpenStackPort object containing changes to apply + * @return boolean on whether the object was updated or not + */ + + public boolean updatePort(String uuid, NeutronPort delta); + + /** + * Applications call this interface method to see if a MAC address is in use + * + * @param macAddress + * mac Address to be tested + * @return boolean on whether the macAddress is already associated with a + * port or not + */ + + public boolean macInUse(String macAddress); + + /** + * Applications call this interface method to retrieve the port associated with + * the gateway address of a subnet + * + * @param subnetUUID + * identifier of the subnet + * @return OpenStackPorts object if the port exists and null if it does not + */ + + public NeutronPort getGatewayPort(String subnetUUID); +} diff --git a/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronRouterAware.java b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronRouterAware.java new file mode 100644 index 0000000000..16a9aec239 --- /dev/null +++ b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronRouterAware.java @@ -0,0 +1,105 @@ +/* + * Copyright IBM Corporation, 2013. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.networkconfig.neutron; + +/** + * This interface defines the methods a service that wishes to be aware of Neutron Routers needs to implement + * + */ + +public interface INeutronRouterAware { + + /** + * Services provide this interface method to indicate if the specified router can be created + * + * @param router + * instance of proposed new Neutron Router object + * @return integer + * the return value is understood to be a HTTP status code. A return value outside of 200 through 299 + * results in the create operation being interrupted and the returned status value reflected in the + * HTTP response. + */ + public int canCreateRouter(NeutronRouter router); + + /** + * Services provide this interface method for taking action after a router has been created + * + * @param router + * instance of new Neutron Router object + * @return void + */ + public void neutronRouterCreated(NeutronRouter router); + + /** + * Services provide this interface method to indicate if the specified router can be changed using the specified + * delta + * + * @param delta + * updates to the router object using patch semantics + * @param router + * instance of the Neutron Router object to be updated + * @return integer + * the return value is understood to be a HTTP status code. A return value outside of 200 through 299 + * results in the update operation being interrupted and the returned status value reflected in the + * HTTP response. + */ + public int canUpdateRouter(NeutronRouter delta, NeutronRouter original); + + /** + * Services provide this interface method for taking action after a router has been updated + * + * @param router + * instance of modified Neutron Router object + * @return void + */ + public void neutronRouterUpdated(NeutronRouter router); + + /** + * Services provide this interface method to indicate if the specified router can be deleted + * + * @param router + * instance of the Neutron Router object to be deleted + * @return integer + * the return value is understood to be a HTTP status code. A return value outside of 200 through 299 + * results in the delete operation being interrupted and the returned status value reflected in the + * HTTP response. + */ + public int canDeleteRouter(NeutronRouter router); + + /** + * Services provide this interface method for taking action after a router has been deleted + * + * @param router + * instance of deleted Router Network object + * @return void + */ + public void neutronRouterDeleted(NeutronRouter router); + + /** + * Services provide this interface method for taking action after an interface has been added to a router + * + * @param router + * instance of the base Neutron Router object + * @param routerInterface + * instance of the NeutronRouter_Interface being attached to the router + * @return void + */ + public void neutronRouterInterfaceAttached(NeutronRouter router, NeutronRouter_Interface routerInterface); + + /** + * Services provide this interface method for taking action after an interface has been removed from a router + * + * @param router + * instance of the base Neutron Router object + * @param routerInterface + * instance of the NeutronRouter_Interface being detached from the router + * @return void + */ + public void neutronRouterInterfaceDetached(NeutronRouter router, NeutronRouter_Interface routerInterface); +} diff --git a/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronRouterCRUD.java b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronRouterCRUD.java new file mode 100644 index 0000000000..19be16d68e --- /dev/null +++ b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronRouterCRUD.java @@ -0,0 +1,93 @@ +/* + * Copyright IBM Corporation, 2013. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.networkconfig.neutron; + +import java.util.List; + +/** + * This interface defines the methods for CRUD of NB Router objects + * + */ + +public interface INeutronRouterCRUD { + /** + * Applications call this interface method to determine if a particular + * Router object exists + * + * @param uuid + * UUID of the Router object + * @return boolean + */ + + public boolean routerExists(String uuid); + + /** + * Applications call this interface method to return if a particular + * Router object exists + * + * @param uuid + * UUID of the Router object + * @return {@link org.opendaylight.controller.networkconfig.neutron.NeutronRouter.OpenStackRouters} + * OpenStack Router class + */ + + public NeutronRouter getRouter(String uuid); + + /** + * Applications call this interface method to return all Router objects + * + * @return List of OpenStackRouters objects + */ + + public List getAllRouters(); + + /** + * Applications call this interface method to add a Router object to the + * concurrent map + * + * @param input + * OpenStackRouter object + * @return boolean on whether the object was added or not + */ + + public boolean addRouter(NeutronRouter input); + + /** + * Applications call this interface method to remove a Router object to the + * concurrent map + * + * @param uuid + * identifier for the Router object + * @return boolean on whether the object was removed or not + */ + + public boolean removeRouter(String uuid); + + /** + * Applications call this interface method to edit a Router object + * + * @param uuid + * identifier of the Router object + * @param delta + * OpenStackRouter object containing changes to apply + * @return boolean on whether the object was updated or not + */ + + public boolean updateRouter(String uuid, NeutronRouter delta); + + /** + * Applications call this interface method to check if a router is in use + * + * @param uuid + * identifier of the Router object + * @return boolean on whether the router is in use or not + */ + + public boolean routerInUse(String routerUUID); +} diff --git a/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronSubnetAware.java b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronSubnetAware.java new file mode 100644 index 0000000000..b7bafab04c --- /dev/null +++ b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronSubnetAware.java @@ -0,0 +1,84 @@ +/* + * Copyright IBM Corporation, 2013. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.networkconfig.neutron; + +/** + * This interface defines the methods a service that wishes to be aware of Neutron Subnets needs to implement + * + */ + +public interface INeutronSubnetAware { + + /** + * Services provide this interface method to indicate if the specified subnet can be created + * + * @param subnet + * instance of proposed new Neutron Subnet object + * @return integer + * the return value is understood to be a HTTP status code. A return value outside of 200 through 299 + * results in the create operation being interrupted and the returned status value reflected in the + * HTTP response. + */ + public int canCreateSubnet(NeutronSubnet subnet); + + /** + * Services provide this interface method for taking action after a subnet has been created + * + * @param subnet + * instance of new Neutron Subnet object + * @return void + */ + public void neutronSubnetCreated(NeutronSubnet subnet); + + /** + * Services provide this interface method to indicate if the specified subnet can be changed using the specified + * delta + * + * @param delta + * updates to the subnet object using patch semantics + * @param subnet + * instance of the Neutron Subnet object to be updated + * @return integer + * the return value is understood to be a HTTP status code. A return value outside of 200 through 299 + * results in the update operation being interrupted and the returned status value reflected in the + * HTTP response. + */ + public int canUpdateSubnet(NeutronSubnet delta, NeutronSubnet original); + + /** + * Services provide this interface method for taking action after a subnet has been updated + * + * @param subnet + * instance of modified Neutron Subnet object + * @return void + */ + public void neutronSubnetUpdated(NeutronSubnet subnet); + + /** + * Services provide this interface method to indicate if the specified subnet can be deleted + * + * @param subnet + * instance of the Subnet Router object to be deleted + * @return integer + * the return value is understood to be a HTTP status code. A return value outside of 200 through 299 + * results in the delete operation being interrupted and the returned status value reflected in the + * HTTP response. + */ + public int canDeleteSubnet(NeutronSubnet subnet); + + /** + * Services provide this interface method for taking action after a subnet has been deleted + * + * @param subnet + * instance of deleted Router Subnet object + * @return void + */ + public void neutronSubnetDeleted(NeutronSubnet subnet); + +} diff --git a/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronSubnetCRUD.java b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronSubnetCRUD.java new file mode 100644 index 0000000000..9c390467e5 --- /dev/null +++ b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/INeutronSubnetCRUD.java @@ -0,0 +1,95 @@ +/* + * Copyright IBM Corporation, 2013. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.networkconfig.neutron; + +import java.util.List; + +/** + * This interface defines the methods for CRUD of NB Subnet objects + * + */ + +public interface INeutronSubnetCRUD { + /** + * Applications call this interface method to determine if a particular + * Subnet object exists + * + * @param uuid + * UUID of the Subnet object + * @return boolean + */ + + public boolean subnetExists(String uuid); + + /** + * Applications call this interface method to return if a particular + * Subnet object exists + * + * @param uuid + * UUID of the Subnet object + * @return {@link org.opendaylight.controller.networkconfig.neutron.NeutronSubnet.OpenStackSubnets} + * OpenStack Subnet class + */ + + public NeutronSubnet getSubnet(String uuid); + + /** + * Applications call this interface method to return all Subnet objects + * + * @return List of OpenStackSubnets objects + */ + + public List getAllSubnets(); + + /** + * Applications call this interface method to add a Subnet object to the + * concurrent map + * + * @param input + * OpenStackSubnet object + * @return boolean on whether the object was added or not + */ + + public boolean addSubnet(NeutronSubnet input); + + /** + * Applications call this interface method to remove a Subnet object to the + * concurrent map + * + * @param uuid + * identifier for the Subnet object + * @return boolean on whether the object was removed or not + */ + + public boolean removeSubnet(String uuid); + + /** + * Applications call this interface method to edit a Subnet object + * + * @param uuid + * identifier of the Subnet object + * @param delta + * OpenStackSubnet object containing changes to apply + * @return boolean on whether the object was updated or not + */ + + public boolean updateSubnet(String uuid, NeutronSubnet delta); + + /** + * Applications call this interface method to determine if a Subnet object + * is use + * + * @param subnetUUID + * identifier of the subnet object + * + * @return boolean on whether the subnet is in use or not + */ + + public boolean subnetInUse(String subnetUUID); +} diff --git a/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronCRUDInterfaces.java b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronCRUDInterfaces.java new file mode 100644 index 0000000000..0becb475b8 --- /dev/null +++ b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronCRUDInterfaces.java @@ -0,0 +1,39 @@ +/* + * Copyright IBM Corporation, 2013. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.networkconfig.neutron; + +import org.opendaylight.controller.sal.utils.ServiceHelper; + +public class NeutronCRUDInterfaces { + + public static INeutronNetworkCRUD getINeutronNetworkCRUD(Object o) { + INeutronNetworkCRUD answer = (INeutronNetworkCRUD) ServiceHelper.getGlobalInstance(INeutronNetworkCRUD.class, o); + return answer; + } + + public static INeutronSubnetCRUD getINeutronSubnetCRUD(Object o) { + INeutronSubnetCRUD answer = (INeutronSubnetCRUD) ServiceHelper.getGlobalInstance(INeutronSubnetCRUD.class, o); + return answer; + } + + public static INeutronPortCRUD getINeutronPortCRUD(Object o) { + INeutronPortCRUD answer = (INeutronPortCRUD) ServiceHelper.getGlobalInstance(INeutronPortCRUD.class, o); + return answer; + } + + public static INeutronRouterCRUD getINeutronRouterCRUD(Object o) { + INeutronRouterCRUD answer = (INeutronRouterCRUD) ServiceHelper.getGlobalInstance(INeutronRouterCRUD.class, o); + return answer; + } + + public static INeutronFloatingIPCRUD getINeutronFloatingIPCRUD(Object o) { + INeutronFloatingIPCRUD answer = (INeutronFloatingIPCRUD) ServiceHelper.getGlobalInstance(INeutronFloatingIPCRUD.class, o); + return answer; + } +} diff --git a/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronFloatingIP.java b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronFloatingIP.java new file mode 100644 index 0000000000..906b4d4e76 --- /dev/null +++ b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronFloatingIP.java @@ -0,0 +1,130 @@ +/* + * Copyright IBM Corporation, 2013. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.networkconfig.neutron; + +import java.util.Iterator; +import java.util.List; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) + +public class NeutronFloatingIP { + // See OpenStack Network API v2.0 Reference for description of + // annotated attributes + + @XmlElement (name="id") + String floatingIPUUID; + + @XmlElement (name="floating_network_id") + String floatingNetworkUUID; + + @XmlElement (name="port_id") + String portUUID; + + @XmlElement (name="fixed_ip_address") + String fixedIPAddress; + + @XmlElement (name="floating_ip_address") + String floatingIPAddress; + + @XmlElement (name="tenant_id") + String tenantUUID; + + public NeutronFloatingIP() { + } + + public String getID() { return floatingIPUUID; } + + public String getFloatingIPUUID() { + return floatingIPUUID; + } + + public void setFloatingIPUUID(String floatingIPUUID) { + this.floatingIPUUID = floatingIPUUID; + } + + public String getFloatingNetworkUUID() { + return floatingNetworkUUID; + } + + public void setFloatingNetworkUUID(String floatingNetworkUUID) { + this.floatingNetworkUUID = floatingNetworkUUID; + } + + public String getPortUUID() { + return portUUID; + } + + public void setPortUUID(String portUUID) { + this.portUUID = portUUID; + } + + public String getFixedIPAddress() { + return fixedIPAddress; + } + + public void setFixedIPAddress(String fixedIPAddress) { + this.fixedIPAddress = fixedIPAddress; + } + + public String getFloatingIPAddress() { + return floatingIPAddress; + } + + public void setFloatingIPAddress(String floatingIPAddress) { + this.floatingIPAddress = floatingIPAddress; + } + + public String getTenantUUID() { + return tenantUUID; + } + + public void setTenantUUID(String tenantUUID) { + this.tenantUUID = tenantUUID; + } + + /** + * This method copies selected fields from the object and returns them + * as a new object, suitable for marshaling. + * + * @param fields + * List of attributes to be extracted + * @return an OpenStackFloatingIPs object with only the selected fields + * populated + */ + + public NeutronFloatingIP extractFields(List fields) { + NeutronFloatingIP ans = new NeutronFloatingIP(); + Iterator i = fields.iterator(); + while (i.hasNext()) { + String s = i.next(); + if (s.equals("id")) + ans.setFloatingIPUUID(this.getFloatingIPUUID()); + if (s.equals("floating_network_id")) + ans.setFloatingNetworkUUID(this.getFloatingNetworkUUID()); + if (s.equals("port_id")) + ans.setPortUUID(this.getPortUUID()); + if (s.equals("fixed_ip_address")) + ans.setFixedIPAddress(this.getFixedIPAddress()); + if (s.equals("floating_ip_address")) + ans.setFloatingIPAddress(this.getFloatingIPAddress()); + if (s.equals("tenant_id")) + ans.setTenantUUID(this.getTenantUUID()); + } + return ans; + } + + public void initDefaults() { + } +} diff --git a/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronNetwork.java b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronNetwork.java new file mode 100644 index 0000000000..eccbbcc346 --- /dev/null +++ b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronNetwork.java @@ -0,0 +1,233 @@ +/* + * Copyright IBM Corporation, 2013. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.networkconfig.neutron; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement(name = "network") +@XmlAccessorType(XmlAccessType.NONE) + +public class NeutronNetwork { + // See OpenStack Network API v2.0 Reference for description of + // annotated attributes + + @XmlElement (name="id") + String networkUUID; // network UUID + + @XmlElement (name="name") + String networkName; // name + + @XmlElement (defaultValue="true", name="admin_state_up") + Boolean adminStateUp; // admin state up (true/false) + + @XmlElement (defaultValue="false", name="shared") + Boolean shared; // shared network or not + + @XmlElement (name="tenant_id") + String tenantID; // tenant for this network + + @XmlElement (defaultValue="false", namespace="router", name="external") + Boolean routerExternal; // network external or not + + @XmlElement (defaultValue="flat", namespace="provider", name="network_type") + String providerNetworkType; // provider network type (flat or vlan) + + @XmlElement (namespace="provider", name="physical_network") + String providerPhysicalNetwork; // provider physical network (name) + + @XmlElement (namespace="provider", name="segmentation_id") + String providerSegmentationID; // provide segmentation ID (vlan ID) + + @XmlElement (name="status") + String status; // status (read-only) + + @XmlElement (name="subnets") + List subnets; // subnets (read-only) + + /* This attribute lists the ports associated with an instance + * which is needed for determining if that instance can be deleted + */ + + List myPorts; + + public NeutronNetwork() { + myPorts = new ArrayList(); + } + + public void initDefaults() { + subnets = new ArrayList(); + if (this.status == null) + this.status = "ACTIVE"; + if (this.adminStateUp == null) + this.adminStateUp = true; + if (this.shared == null) + this.shared = false; + if (this.routerExternal == null) + this.routerExternal = false; + if (this.providerNetworkType == null) + this.providerNetworkType = "flat"; + } + + public String getID() { return networkUUID; } + + public String getNetworkUUID() { + return networkUUID; + } + + public void setNetworkUUID(String networkUUID) { + this.networkUUID = networkUUID; + } + + public String getNetworkName() { + return networkName; + } + + public void setNetworkName(String networkName) { + this.networkName = networkName; + } + + public boolean isAdminStateUp() { + return adminStateUp; + } + + public Boolean getAdminStateUp() { return adminStateUp; } + + public void setAdminStateUp(boolean newValue) { + this.adminStateUp = newValue; + } + + public boolean isShared() { return shared; } + + public Boolean getShared() { return shared; } + + public void setShared(boolean newValue) { + this.shared = newValue; + } + + public String getTenantID() { + return tenantID; + } + + public void setTenantID(String tenantID) { + this.tenantID = tenantID; + } + + public boolean isRouterExternal() { return routerExternal; } + + public Boolean getRouterExternal() { return routerExternal; } + + public void setRouterExternal(boolean newValue) { + this.routerExternal = newValue; + } + + public String getProviderNetworkType() { + return providerNetworkType; + } + + public void setProviderNetworkType(String providerNetworkType) { + this.providerNetworkType = providerNetworkType; + } + + public String getProviderPhysicalNetwork() { + return providerPhysicalNetwork; + } + + public void setProviderPhysicalNetwork(String providerPhysicalNetwork) { + this.providerPhysicalNetwork = providerPhysicalNetwork; + } + + public String getProviderSegmentationID() { + return providerSegmentationID; + } + + public void setProviderSegmentationID(String providerSegmentationID) { + this.providerSegmentationID = providerSegmentationID; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public List getSubnets() { + return subnets; + } + + public void setSubnets(List subnets) { + this.subnets = subnets; + } + + public void addSubnet(String uuid) { + this.subnets.add(uuid); + } + + public void removeSubnet(String uuid) { + this.subnets.remove(uuid); + } + + public List getPortsOnNetwork() { + return myPorts; + } + + public void addPort(NeutronPort port) { + myPorts.add(port); + } + + public void removePort(NeutronPort port) { + myPorts.remove(port); + } + + /** + * This method copies selected fields from the object and returns them + * as a new object, suitable for marshaling. + * + * @param fields + * List of attributes to be extracted + * @return an OpenStackNetworks object with only the selected fields + * populated + */ + + public NeutronNetwork extractFields(List fields) { + NeutronNetwork ans = new NeutronNetwork(); + Iterator i = fields.iterator(); + while (i.hasNext()) { + String s = i.next(); + if (s.equals("id")) + ans.setNetworkUUID(this.getNetworkUUID()); + if (s.equals("name")) + ans.setNetworkName(this.getNetworkName()); + if (s.equals("admin_state_up")) + ans.setAdminStateUp(this.adminStateUp); + if (s.equals("status")) + ans.setStatus(this.getStatus()); + if (s.equals("subnets")) { + List subnetList = new ArrayList(); + subnetList.addAll(this.getSubnets()); + ans.setSubnets(subnetList); + } + if (s.equals("shared")) + ans.setShared(this.shared); + if (s.equals("tenant_id")) + ans.setTenantID(this.getTenantID()); + } + return ans; + } + +} + diff --git a/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronPort.java b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronPort.java new file mode 100644 index 0000000000..7f7f712bed --- /dev/null +++ b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronPort.java @@ -0,0 +1,239 @@ +/* + * Copyright IBM Corporation, 2013. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.networkconfig.neutron; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + + +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) + +public class NeutronPort { + // See OpenStack Network API v2.0 Reference for description of + // annotated attributes + + @XmlElement (name="id") + String portUUID; + + @XmlElement (name="network_id") + String networkUUID; + + @XmlElement (name="name") + String name; + + @XmlElement (defaultValue="true", name="admin_state_up") + Boolean adminStateUp; + + @XmlElement (name="status") + String status; + + @XmlElement (name="mac_address") + String macAddress; + + @XmlElement (name="fixed_ips") + List fixedIPs; + + @XmlElement (name="device_id") + String deviceID; + + @XmlElement (name="device_owner") + String deviceOwner; + + @XmlElement (name="tenant_id") + String tenantID; + + // TODO: add security groups + // @XmlElement (name="security_groups") + // List securityGroups; + + /* this attribute stores the floating IP address assigned to + * each fixed IP address + */ + + HashMap floatingIPMap; + + public NeutronPort() { + floatingIPMap = new HashMap(); + } + + public String getID() { return portUUID; } + + public String getPortUUID() { + return portUUID; + } + + public void setPortUUID(String portUUID) { + this.portUUID = portUUID; + } + + public String getNetworkUUID() { + return networkUUID; + } + + public void setNetworkUUID(String networkUUID) { + this.networkUUID = networkUUID; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public boolean isAdminStateUp() { + if (adminStateUp == null) + return true; + return adminStateUp; + } + + public Boolean getAdminStateUp() { return adminStateUp; } + + public void setAdminStateUp(Boolean newValue) { + this.adminStateUp = newValue; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getMacAddress() { + return macAddress; + } + + public void setMacAddress(String macAddress) { + this.macAddress = macAddress; + } + + public List getFixedIPs() { + return fixedIPs; + } + + public void setFixedIPs(List fixedIPs) { + this.fixedIPs = fixedIPs; + } + + public String getDeviceID() { + return deviceID; + } + + public void setDeviceID(String deviceID) { + this.deviceID = deviceID; + } + + public String getDeviceOwner() { + return deviceOwner; + } + + public void setDeviceOwner(String deviceOwner) { + this.deviceOwner = deviceOwner; + } + + public String getTenantID() { + return tenantID; + } + + public void setTenantID(String tenantID) { + this.tenantID = tenantID; + } + + public NeutronFloatingIP getFloatingIP(String key) { + if (!floatingIPMap.containsKey(key)) + return null; + return floatingIPMap.get(key); + } + + public void removeFloatingIP(String key) { + floatingIPMap.remove(key); + } + + public void addFloatingIP(String key, NeutronFloatingIP floatingIP) { + if (!floatingIPMap.containsKey(key)) + floatingIPMap.put(key, floatingIP); + } + + /** + * This method copies selected fields from the object and returns them + * as a new object, suitable for marshaling. + * + * @param fields + * List of attributes to be extracted + * @return an OpenStackPorts object with only the selected fields + * populated + */ + + public NeutronPort extractFields(List fields) { + NeutronPort ans = new NeutronPort(); + Iterator i = fields.iterator(); + while (i.hasNext()) { + String s = i.next(); + if (s.equals("id")) + ans.setPortUUID(this.getPortUUID()); + if (s.equals("network_id")) + ans.setNetworkUUID(this.getNetworkUUID()); + if (s.equals("name")) + ans.setName(this.getName()); + if (s.equals("admin_state_up")) + ans.setAdminStateUp(this.getAdminStateUp()); + if (s.equals("status")) + ans.setStatus(this.getStatus()); + if (s.equals("mac_address")) + ans.setMacAddress(this.getMacAddress()); + if (s.equals("fixed_ips")) { + List fixedIPs = new ArrayList(); + fixedIPs.addAll(this.getFixedIPs()); + ans.setFixedIPs(fixedIPs); + } + if (s.equals("device_id")) { + ans.setDeviceID(this.getDeviceID()); + } + if (s.equals("device_owner")) { + ans.setDeviceOwner(this.getDeviceOwner()); + } + if (s.equals("tenant_id")) + ans.setTenantID(this.getTenantID()); + } + return ans; + } + + public void initDefaults() { + adminStateUp = true; + if (status == null) + status = "ACTIVE"; + if (fixedIPs == null) + fixedIPs = new ArrayList(); + } + + /** + * This method checks to see if the port has a floating IPv4 address + * associated with the supplied fixed IPv4 address + * + * @param fixedIP + * fixed IPv4 address in dotted decimal format + * @return a boolean indicating if there is a floating IPv4 address bound + * to the fixed IPv4 address + */ + + public boolean isBoundToFloatingIP(String fixedIP) { + return floatingIPMap.containsKey(fixedIP); + } +} diff --git a/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronRouter.java b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronRouter.java new file mode 100644 index 0000000000..8329ffc58f --- /dev/null +++ b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronRouter.java @@ -0,0 +1,153 @@ +/* + * Copyright IBM Corporation, 2013. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.networkconfig.neutron; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) + +public class NeutronRouter { + // See OpenStack Network API v2.0 Reference for description of + // annotated attributes + @XmlElement (name="id") + String routerUUID; + + @XmlElement (name="name") + String name; + + @XmlElement (defaultValue="true", name="admin_state_up") + Boolean adminStateUp; + + @XmlElement (name="status") + String status; + + @XmlElement (name="tenant_id") + String tenantID; + + @XmlElement (name="external_gateway_info") + NeutronRouter_NetworkReference externalGatewayInfo; + + /* Holds a map of OpenStackRouterInterfaces by subnet UUID + * used for internal mapping to DOVE + */ + HashMap interfaces; + + public NeutronRouter() { + interfaces = new HashMap(); + } + + public String getID() { return routerUUID; } + + public String getRouterUUID() { + return routerUUID; + } + + public void setRouterUUID(String routerUUID) { + this.routerUUID = routerUUID; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public boolean isAdminStateUp() { + if (adminStateUp == null) + return true; + return adminStateUp; + } + + public Boolean getAdminStateUp() { return adminStateUp; } + + public void setAdminStateUp(Boolean newValue) { + this.adminStateUp = newValue; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getTenantID() { + return tenantID; + } + + public void setTenantID(String tenantID) { + this.tenantID = tenantID; + } + + public NeutronRouter_NetworkReference getExternalGatewayInfo() { + return externalGatewayInfo; + } + + public void setExternalGatewayInfo(NeutronRouter_NetworkReference externalGatewayInfo) { + this.externalGatewayInfo = externalGatewayInfo; + } + + /** + * This method copies selected fields from the object and returns them + * as a new object, suitable for marshaling. + * + * @param fields + * List of attributes to be extracted + * @return an OpenStackRouters object with only the selected fields + * populated + */ + + public NeutronRouter extractFields(List fields) { + NeutronRouter ans = new NeutronRouter(); + Iterator i = fields.iterator(); + while (i.hasNext()) { + String s = i.next(); + if (s.equals("id")) + ans.setRouterUUID(this.getRouterUUID()); + if (s.equals("name")) + ans.setName(this.getName()); + if (s.equals("admin_state_up")) + ans.setAdminStateUp(this.getAdminStateUp()); + if (s.equals("status")) + ans.setStatus(this.getStatus()); + if (s.equals("tenant_id")) + ans.setTenantID(this.getTenantID()); + if (s.equals("external_gateway_info")) { + ans.setExternalGatewayInfo(this.getExternalGatewayInfo()); + } + } + return ans; + } + + public HashMap getInterfaces() { + return interfaces; + } + + public void addInterface(String s, NeutronRouter_Interface i) { + interfaces.put(s, i); + } + + public void removeInterface(String s) { + interfaces.remove(s); + } + + public void initDefaults() { + adminStateUp = true; + } +} diff --git a/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronRouter_Interface.java b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronRouter_Interface.java new file mode 100644 index 0000000000..307789c8cf --- /dev/null +++ b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronRouter_Interface.java @@ -0,0 +1,65 @@ +/* + * Copyright IBM Corporation, 2013. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.networkconfig.neutron; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) +public class NeutronRouter_Interface { + // See OpenStack Network API v2.0 Reference for description of + // annotated attributes + + @XmlElement (name="subnet_id") + String subnetUUID; + + @XmlElement (name="port_id") + String portUUID; + + @XmlElement (name="id") + String id; + + @XmlElement (name="tenant_id") + String tenantID; + + public NeutronRouter_Interface() { + } + + public NeutronRouter_Interface(String subnetUUID, String portUUID) { + this.subnetUUID = subnetUUID; + this.portUUID = portUUID; + } + + public String getSubnetUUID() { + return subnetUUID; + } + + public void setSubnetUUID(String subnetUUID) { + this.subnetUUID = subnetUUID; + } + + public String getPortUUID() { + return portUUID; + } + + public void setPortUUID(String portUUID) { + this.portUUID = portUUID; + } + + public void setID(String id) { + this.id = id; + } + + public void setTenantID(String tenantID) { + this.tenantID = tenantID; + } +} diff --git a/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronRouter_NetworkReference.java b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronRouter_NetworkReference.java new file mode 100644 index 0000000000..012215c719 --- /dev/null +++ b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronRouter_NetworkReference.java @@ -0,0 +1,36 @@ +/* + * Copyright IBM Corporation, 2013. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.networkconfig.neutron; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) + +public class NeutronRouter_NetworkReference { + // See OpenStack Network API v2.0 Reference for description of + // annotated attributes + + @XmlElement(name="network_id") + String networkID; + + public NeutronRouter_NetworkReference() { + } + + public String getNetworkID() { + return networkID; + } + + public void setNetworkID(String networkID) { + this.networkID = networkID; + } +} diff --git a/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronSubnet.java b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronSubnet.java new file mode 100644 index 0000000000..b1414c3730 --- /dev/null +++ b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronSubnet.java @@ -0,0 +1,403 @@ +/* + * Copyright IBM Corporation, 2013. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.networkconfig.neutron; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +import org.apache.commons.net.util.SubnetUtils; +import org.apache.commons.net.util.SubnetUtils.SubnetInfo; + +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) + +public class NeutronSubnet { + // See OpenStack Network API v2.0 Reference for description of + // annotated attributes + + @XmlElement (name="id") + String subnetUUID; + + @XmlElement (name="network_id") + String networkUUID; + + @XmlElement (name="name") + String name; + + @XmlElement (defaultValue="4", name="ip_version") + Integer ipVersion; + + @XmlElement (name="cidr") + String cidr; + + @XmlElement (name="gateway_ip") + String gatewayIP; + + @XmlElement (name="dns_nameservers") + List dnsNameservers; + + @XmlElement (name="allocation_pools") + List allocationPools; + + @XmlElement (name="host_routes") + List hostRoutes; + + @XmlElement (defaultValue="true", name="enable_dhcp") + Boolean enableDHCP; + + @XmlElement (name="tenant_id") + String tenantID; + + /* stores the OpenStackPorts associated with an instance + * used to determine if that instance can be deleted. + */ + List myPorts; + + boolean gatewayIPAssigned; + + public NeutronSubnet() { + myPorts = new ArrayList(); + } + + public String getID() { return subnetUUID; } + + public String getSubnetUUID() { + return subnetUUID; + } + + public void setSubnetUUID(String subnetUUID) { + this.subnetUUID = subnetUUID; + } + + public String getNetworkUUID() { + return networkUUID; + } + + public void setNetworkUUID(String networkUUID) { + this.networkUUID = networkUUID; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Integer getIpVersion() { + return ipVersion; + } + + public void setIpVersion(Integer ipVersion) { + this.ipVersion = ipVersion; + } + + public String getCidr() { + return cidr; + } + + public void setCidr(String cidr) { + this.cidr = cidr; + } + + public String getGatewayIP() { + return gatewayIP; + } + + public void setGatewayIP(String gatewayIP) { + this.gatewayIP = gatewayIP; + } + + public List getDnsNameservers() { + return dnsNameservers; + } + + public void setDnsNameservers(List dnsNameservers) { + this.dnsNameservers = dnsNameservers; + } + + public List getAllocationPools() { + return allocationPools; + } + + public void setAllocationPools(List allocationPools) { + this.allocationPools = allocationPools; + } + + public List getHostRoutes() { + return hostRoutes; + } + + public void setHostRoutes(List hostRoutes) { + this.hostRoutes = hostRoutes; + } + + public boolean isEnableDHCP() { + if (enableDHCP == null) + return true; + return enableDHCP; + } + + public Boolean getEnableDHCP() { return enableDHCP; } + + public void setEnableDHCP(Boolean newValue) { + this.enableDHCP = newValue; + } + + public String getTenantID() { + return tenantID; + } + + public void setTenantID(String tenantID) { + this.tenantID = tenantID; + } + + /** + * This method copies selected fields from the object and returns them + * as a new object, suitable for marshaling. + * + * @param fields + * List of attributes to be extracted + * @return an OpenStackSubnets object with only the selected fields + * populated + */ + + public NeutronSubnet extractFields(List fields) { + NeutronSubnet ans = new NeutronSubnet(); + Iterator i = fields.iterator(); + while (i.hasNext()) { + String s = i.next(); + if (s.equals("id")) + ans.setSubnetUUID(this.getSubnetUUID()); + if (s.equals("network_id")) + ans.setNetworkUUID(this.getNetworkUUID()); + if (s.equals("name")) + ans.setName(this.getName()); + if (s.equals("ip_version")) + ans.setIpVersion(this.getIpVersion()); + if (s.equals("cidr")) + ans.setCidr(this.getCidr()); + if (s.equals("gateway_ip")) + ans.setGatewayIP(this.getGatewayIP()); + if (s.equals("dns_nameservers")) { + List nsList = new ArrayList(); + nsList.addAll(this.getDnsNameservers()); + ans.setDnsNameservers(nsList); + } + if (s.equals("allocation_pools")) { + List aPools = new ArrayList(); + aPools.addAll(this.getAllocationPools()); + ans.setAllocationPools(aPools); + } + if (s.equals("host_routes")) { + List hRoutes = new ArrayList(); + hRoutes.addAll(this.getHostRoutes()); + ans.setHostRoutes(hRoutes); + } + if (s.equals("enable_dhcp")) + ans.setEnableDHCP(this.getEnableDHCP()); + if (s.equals("tenant_id")) + ans.setTenantID(this.getTenantID()); + } + return ans; + } + + /* test to see if the cidr address used to define this subnet + * is a valid network address (an necessary condition when creating + * a new subnet) + */ + public boolean isValidCIDR() { + try { + SubnetUtils util = new SubnetUtils(cidr); + SubnetInfo info = util.getInfo(); + if (!info.getNetworkAddress().equals(info.getAddress())) + return false; + } catch (Exception e) { + return false; + } + return true; + } + + /* test to see if the gateway IP specified overlaps with specified + * allocation pools (an error condition when creating a new subnet + * or assigning a gateway IP) + */ + public boolean gatewayIP_Pool_overlap() { + Iterator i = allocationPools.iterator(); + while (i.hasNext()) { + NeutronSubnet_IPAllocationPool pool = i.next(); + if (pool.contains(gatewayIP)) + return true; + } + return false; + } + + public void initDefaults() { + if (enableDHCP == null) + enableDHCP = true; + if (ipVersion == null) + ipVersion = 4; + gatewayIPAssigned = false; + dnsNameservers = new ArrayList(); + allocationPools = new ArrayList(); + hostRoutes = new ArrayList(); + try { + SubnetUtils util = new SubnetUtils(cidr); + SubnetInfo info = util.getInfo(); + if (gatewayIP == null) + gatewayIP = info.getLowAddress(); + if (allocationPools.size() < 1) { + NeutronSubnet_IPAllocationPool source = + new NeutronSubnet_IPAllocationPool(info.getLowAddress(), + info.getHighAddress()); + allocationPools = source.splitPool(gatewayIP); + } + } catch (Exception e) { + ; + } + } + + public List getPortsInSubnet() { + return myPorts; + } + + public void addPort(NeutronPort port) { + myPorts.add(port); + } + + public void removePort(NeutronPort port) { + myPorts.remove(port); + } + + /* this method tests to see if the supplied IPv4 address + * is valid for this subnet or not + */ + public boolean isValidIP(String ipAddress) { + try { + SubnetUtils util = new SubnetUtils(cidr); + SubnetInfo info = util.getInfo(); + return info.isInRange(ipAddress); + } catch (Exception e) { + return false; + } + } + + /* test to see if the supplied IPv4 address is part of one of the + * available allocation pools or not + */ + public boolean isIPInUse(String ipAddress) { + if (ipAddress.equals(gatewayIP) && !gatewayIPAssigned ) + return false; + Iterator i = allocationPools.iterator(); + while (i.hasNext()) { + NeutronSubnet_IPAllocationPool pool = i.next(); + if (pool.contains(ipAddress)) + return false; + } + return true; + } + + /* method to get the lowest available address of the subnet. + * go through all the allocation pools and keep the lowest of their + * low addresses. + */ + public String getLowAddr() { + String ans = null; + Iterator i = allocationPools.iterator(); + while (i.hasNext()) { + NeutronSubnet_IPAllocationPool pool = i.next(); + if (ans == null) + ans = pool.getPoolStart(); + else + if (NeutronSubnet_IPAllocationPool.convert(pool.getPoolStart()) < + NeutronSubnet_IPAllocationPool.convert(ans)) + ans = pool.getPoolStart(); + } + return ans; + } + + /* + * allocate the parameter address. Because this uses an iterator to + * check the instance's list of allocation pools and we want to modify + * pools while the iterator is being used, it is necessary to + * build a new list of allocation pools and replace the list when + * finished (otherwise a split will cause undefined iterator behavior. + */ + public void allocateIP(String ipAddress) { + Iterator i = allocationPools.iterator(); + List newList = new ArrayList(); // we have to modify a separate list + while (i.hasNext()) { + NeutronSubnet_IPAllocationPool pool = i.next(); + if (pool.getPoolEnd().equalsIgnoreCase(ipAddress) && + pool.getPoolStart().equalsIgnoreCase(ipAddress)) + ; // do nothing, i.e. don't add the current pool to the new list + else + if (pool.contains(ipAddress)) { + List pools = pool.splitPool(ipAddress); + newList.addAll(pools); + } else + newList.add(pool); + } + allocationPools = newList; + } + + /* + * release an IP address back to the subnet. Although an iterator + * is used, the list is not modified until the iterator is complete, so + * an extra list is not necessary. + */ + public void releaseIP(String ipAddress) { + NeutronSubnet_IPAllocationPool lPool = null; + NeutronSubnet_IPAllocationPool hPool = null; + Iterator i = allocationPools.iterator(); + long sIP = NeutronSubnet_IPAllocationPool.convert(ipAddress); + //look for lPool where ipAddr - 1 is high address + //look for hPool where ipAddr + 1 is low address + while (i.hasNext()) { + NeutronSubnet_IPAllocationPool pool = i.next(); + long lIP = NeutronSubnet_IPAllocationPool.convert(pool.getPoolStart()); + long hIP = NeutronSubnet_IPAllocationPool.convert(pool.getPoolEnd()); + if (sIP+1 == lIP) + hPool = pool; + if (sIP-1 == hIP) + lPool = pool; + } + //if (lPool == NULL and hPool == NULL) create new pool where low = ip = high + if (lPool == null && hPool == null) + allocationPools.add(new NeutronSubnet_IPAllocationPool(ipAddress,ipAddress)); + //if (lPool == NULL and hPool != NULL) change low address of hPool to ipAddr + if (lPool == null && hPool != null) + hPool.setPoolStart(ipAddress); + //if (lPool != NULL and hPool == NULL) change high address of lPool to ipAddr + if (lPool != null && hPool == null) + lPool.setPoolEnd(ipAddress); + //if (lPool != NULL and hPool != NULL) remove lPool and hPool and create new pool + // where low address = lPool.low address and high address = hPool.high Address + if (lPool != null && hPool != null) { + allocationPools.remove(lPool); + allocationPools.remove(hPool); + allocationPools.add(new NeutronSubnet_IPAllocationPool( + lPool.getPoolStart(), hPool.getPoolEnd())); + } + } + + public void setGatewayIPAllocated() { + gatewayIPAssigned = true; + } + + public void resetGatewayIPAllocated() { + gatewayIPAssigned = false; + } +} diff --git a/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronSubnet_HostRoute.java b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronSubnet_HostRoute.java new file mode 100644 index 0000000000..c1084297ba --- /dev/null +++ b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronSubnet_HostRoute.java @@ -0,0 +1,29 @@ +/* + * Copyright IBM Corporation, 2013. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.networkconfig.neutron; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) +public class NeutronSubnet_HostRoute { + // See OpenStack Network API v2.0 Reference for description of + // annotated attributes + + @XmlElement(name="destination") + String destination; + + @XmlElement(name="nexthop") + String nextHop; + + public NeutronSubnet_HostRoute() { } +} diff --git a/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronSubnet_IPAllocationPool.java b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronSubnet_IPAllocationPool.java new file mode 100644 index 0000000000..15401b7522 --- /dev/null +++ b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/NeutronSubnet_IPAllocationPool.java @@ -0,0 +1,171 @@ +/* + * Copyright IBM Corporation, 2013. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.networkconfig.neutron; + +import java.util.ArrayList; +import java.util.List; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) +public class NeutronSubnet_IPAllocationPool { + // See OpenStack Network API v2.0 Reference for description of + // annotated attributes + + @XmlElement(name="start") + String poolStart; + + @XmlElement(name="end") + String poolEnd; + + public NeutronSubnet_IPAllocationPool() { } + + public NeutronSubnet_IPAllocationPool(String lowAddress, String highAddress) { + poolStart = lowAddress; + poolEnd = highAddress; + } + + public String getPoolStart() { + return poolStart; + } + + public void setPoolStart(String poolStart) { + this.poolStart = poolStart; + } + + public String getPoolEnd() { + return poolEnd; + } + + public void setPoolEnd(String poolEnd) { + this.poolEnd = poolEnd; + } + + /** + * This method determines if this allocation pool contains the + * input IPv4 address + * + * @param inputString + * IPv4 address in dotted decimal format + * @returns a boolean on whether the pool contains the address or not + */ + + public boolean contains(String inputString) { + long inputIP = convert(inputString); + long startIP = convert(poolStart); + long endIP = convert(poolEnd); + return (inputIP >= startIP && inputIP <= endIP); + } + + /** + * This static method converts the supplied IPv4 address to a long + * integer for comparison + * + * @param inputString + * IPv4 address in dotted decimal format + * @returns high-endian representation of the IPv4 address as a long + */ + + static long convert(String inputString) { + long ans = 0; + String[] parts = inputString.split("\\."); + for (String part: parts) { + ans <<= 8; + ans |= Integer.parseInt(part); + } + return ans; + } + + /** + * This static method converts the supplied high-ending long back + * into a dotted decimal representation of an IPv4 address + * + * @param l + * high-endian representation of the IPv4 address as a long + * @returns IPv4 address in dotted decimal format + */ + static String longtoIP(long l) { + int i; + String[] parts = new String[4]; + for (i=0; i<4; i++) { + parts[3-i] = String.valueOf(l & 255); + l >>= 8; + } + return join(parts,"."); + } + + /* + * helper routine used by longtoIP + */ + public static String join(String r[],String d) + { + if (r.length == 0) return ""; + StringBuilder sb = new StringBuilder(); + int i; + for(i=0;i splitPool(String ipAddress) { + List ans = new ArrayList(); + long gIP = NeutronSubnet_IPAllocationPool.convert(ipAddress); + long sIP = NeutronSubnet_IPAllocationPool.convert(poolStart); + long eIP = NeutronSubnet_IPAllocationPool.convert(poolEnd); + long i; + NeutronSubnet_IPAllocationPool p = new NeutronSubnet_IPAllocationPool(); + boolean poolStarted = false; + for (i=sIP; i<=eIP; i++) { + if (i == sIP) { + if (i != gIP) { + p.setPoolStart(poolStart); + poolStarted = true; + } + } + if (i == eIP) { + if (i != gIP) { + p.setPoolEnd(poolEnd); + } else { + p.setPoolEnd(NeutronSubnet_IPAllocationPool.longtoIP(i-1)); + } + ans.add(p); + } + if (i != sIP && i != eIP) { + if (i != gIP) { + if (!poolStarted) { + p.setPoolStart(NeutronSubnet_IPAllocationPool.longtoIP(i)); + poolStarted = true; + } + } else { + p.setPoolEnd(NeutronSubnet_IPAllocationPool.longtoIP(i-1)); + poolStarted = false; + ans.add(p); + p = new NeutronSubnet_IPAllocationPool(); + } + } + } + return ans; + } +} diff --git a/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/Neutron_IPs.java b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/Neutron_IPs.java new file mode 100644 index 0000000000..7309479399 --- /dev/null +++ b/opendaylight/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/Neutron_IPs.java @@ -0,0 +1,49 @@ +/* + * Copyright IBM Corporation, 2013. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.networkconfig.neutron; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) +public class Neutron_IPs { + // See OpenStack Network API v2.0 Reference for description of + // annotated attributes + + @XmlElement(name="ip_address") + String ipAddress; + + @XmlElement(name="subnet_id") + String subnetUUID; + + public Neutron_IPs() { } + + public Neutron_IPs(String uuid) { + this.subnetUUID = uuid; + } + + public String getIpAddress() { + return ipAddress; + } + + public void setIpAddress(String ipAddress) { + this.ipAddress = ipAddress; + } + + public String getSubnetUUID() { + return subnetUUID; + } + + public void setSubnetUUID(String subnetUUID) { + this.subnetUUID = subnetUUID; + } +} diff --git a/opendaylight/northbound/networkconfiguration/neutron/enunciate.xml b/opendaylight/northbound/networkconfiguration/neutron/enunciate.xml new file mode 100644 index 0000000000..b9e4f7ecc1 --- /dev/null +++ b/opendaylight/northbound/networkconfiguration/neutron/enunciate.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + diff --git a/opendaylight/northbound/networkconfiguration/neutron/pom.xml b/opendaylight/northbound/networkconfiguration/neutron/pom.xml new file mode 100644 index 0000000000..6a143d9853 --- /dev/null +++ b/opendaylight/northbound/networkconfiguration/neutron/pom.xml @@ -0,0 +1,120 @@ + + 4.0.0 + + org.opendaylight.controller + commons.opendaylight + 1.4.0-SNAPSHOT + ../../../commons/opendaylight + + + http://nexus.opendaylight.org/content + 1.26.2 + + + + + + opendaylight-release + ${nexusproxy}/repositories/opendaylight.release/ + + + + opendaylight-snapshot + ${nexusproxy}/repositories/opendaylight.snapshot/ + + + + website + ${sitedeploy} + + + org.opendaylight.controller + networkconfig.neutron.northbound + 0.4.0-SNAPSHOT + bundle + + + + + org.codehaus.enunciate + maven-enunciate-plugin + + + org.apache.felix + maven-bundle-plugin + 2.3.6 + true + + + + org.opendaylight.controller.sal.utils, + org.opendaylight.controller.containermanager, + org.opendaylight.controller.northbound.commons, + org.opendaylight.controller.northbound.commons.exception, + org.opendaylight.controller.northbound.commons.utils, + org.opendaylight.controller.networkconfig.neutron, + org.eclipse.persistence.jaxb.rs, + com.sun.jersey.spi.container.servlet, + javax.ws.rs, + javax.ws.rs.core, + javax.xml.bind.annotation, + javax.xml.bind, + org.slf4j, + !org.codehaus.enunciate.jaxrs + + /controller/nb/v2/neutron + + ${project.basedir}/src/main/resources/META-INF + + + + + + + org.opendaylight.controller.thirdparty + com.sun.jersey.jersey-servlet + 1.17-SNAPSHOT + + + org.opendaylight.controller + containermanager + 0.4.0-SNAPSHOT + + + org.opendaylight.controller + sal + 0.5.0-SNAPSHOT + + + org.opendaylight.controller + commons.northbound + 0.4.0-SNAPSHOT + + + org.opendaylight.controller + networkconfig.neutron + 0.4.0-SNAPSHOT + + + org.codehaus.enunciate + enunciate-core-annotations + ${enunciate.version} + + + org.eclipse.persistence + org.eclipse.persistence.moxy + 2.5.0 + + + org.eclipse.persistence + org.eclipse.persistence.core + 2.5.0 + + + org.eclipse.persistence + org.eclipse.persistence.antlr + 2.5.0 + + + \ No newline at end of file diff --git a/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronFloatingIPRequest.java b/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronFloatingIPRequest.java new file mode 100644 index 0000000000..ca1389c724 --- /dev/null +++ b/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronFloatingIPRequest.java @@ -0,0 +1,52 @@ +/* + * Copyright IBM Corporation, 2013. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.networkconfig.neutron.northbound; + +import java.util.List; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +import org.opendaylight.controller.networkconfig.neutron.NeutronFloatingIP; + +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) +public class NeutronFloatingIPRequest { + // See OpenStack Network API v2.0 Reference for description of + // annotated attributes + + @XmlElement(name="floatingip") + NeutronFloatingIP singletonFloatingIP; + + @XmlElement(name="floatingips") + List bulkRequest; + + NeutronFloatingIPRequest() { + } + + NeutronFloatingIPRequest(List bulk) { + bulkRequest = bulk; + singletonFloatingIP = null; + } + + NeutronFloatingIPRequest(NeutronFloatingIP singleton) { + bulkRequest = null; + singletonFloatingIP = singleton; + } + + public NeutronFloatingIP getSingleton() { + return singletonFloatingIP; + } + + public boolean isSingleton() { + return (singletonFloatingIP != null); + } +} diff --git a/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronFloatingIPsNorthbound.java b/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronFloatingIPsNorthbound.java new file mode 100644 index 0000000000..14eaedd63d --- /dev/null +++ b/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronFloatingIPsNorthbound.java @@ -0,0 +1,427 @@ +/* + * Copyright IBM Corporation, 2013. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.networkconfig.neutron.northbound; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import org.codehaus.enunciate.jaxrs.ResponseCode; +import org.codehaus.enunciate.jaxrs.StatusCodes; +import org.opendaylight.controller.networkconfig.neutron.INeutronFloatingIPAware; +import org.opendaylight.controller.networkconfig.neutron.INeutronFloatingIPCRUD; +import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD; +import org.opendaylight.controller.networkconfig.neutron.INeutronPortAware; +import org.opendaylight.controller.networkconfig.neutron.INeutronPortCRUD; +import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD; +import org.opendaylight.controller.networkconfig.neutron.NeutronFloatingIP; +import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork; +import org.opendaylight.controller.networkconfig.neutron.NeutronPort; +import org.opendaylight.controller.networkconfig.neutron.NeutronSubnet; +import org.opendaylight.controller.networkconfig.neutron.Neutron_IPs; +import org.opendaylight.controller.northbound.commons.RestMessages; +import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException; +import org.opendaylight.controller.sal.utils.ServiceHelper; + +/** + * Open DOVE Northbound REST APIs.
+ * This class provides REST APIs for managing the open DOVE + * + *
+ *
+ * Authentication scheme : HTTP Basic
+ * Authentication realm : opendaylight
+ * Transport : HTTP and HTTPS
+ *
+ * HTTPS Authentication is disabled by default. Administrator can enable it in + * tomcat-server.xml after adding a proper keystore / SSL certificate from a + * trusted authority.
+ * More info : + * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration + * + */ + +@Path("/floatingips") +public class NeutronFloatingIPsNorthbound { + + private NeutronFloatingIP extractFields(NeutronFloatingIP o, List fields) { + return o.extractFields(fields); + } + + /** + * Returns a list of all FloatingIPs */ + + @GET + @Produces({ MediaType.APPLICATION_JSON }) + @StatusCodes({ + @ResponseCode(code = 200, condition = "Operation successful"), + @ResponseCode(code = 401, condition = "Unauthorized"), + @ResponseCode(code = 501, condition = "Not Implemented") }) + public Response listFloatingIPs( + // return fields + @QueryParam("fields") List fields, + // note: openstack isn't clear about filtering on lists, so we aren't handling them + @QueryParam("id") String queryID, + @QueryParam("floating_network_id") String queryFloatingNetworkId, + @QueryParam("port_id") String queryPortId, + @QueryParam("fixed_ip_address") String queryFixedIPAddress, + @QueryParam("floating_ip_address") String queryFloatingIPAddress, + @QueryParam("tenant_id") String queryTenantID, + // pagination + @QueryParam("limit") String limit, + @QueryParam("marker") String marker, + @QueryParam("page_reverse") String pageReverse + // sorting not supported + ) { + INeutronFloatingIPCRUD floatingIPInterface = NeutronNBInterfaces.getIfNBFloatingIPCRUD("default",this); + if (floatingIPInterface == null) { + throw new ServiceUnavailableException("Floating IP CRUD Interface " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + List allFloatingIPs = floatingIPInterface.getAllFloatingIPs(); + List ans = new ArrayList(); + Iterator i = allFloatingIPs.iterator(); + while (i.hasNext()) { + NeutronFloatingIP oSS = i.next(); + //match filters: TODO provider extension and router extension + if ((queryID == null || queryID.equals(oSS.getID())) && + (queryFloatingNetworkId == null || queryFloatingNetworkId.equals(oSS.getFloatingNetworkUUID())) && + (queryPortId == null || queryPortId.equals(oSS.getPortUUID())) && + (queryFixedIPAddress == null || queryFixedIPAddress.equals(oSS.getFixedIPAddress())) && + (queryFloatingIPAddress == null || queryFloatingIPAddress.equals(oSS.getFloatingIPAddress())) && + (queryTenantID == null || queryTenantID.equals(oSS.getTenantUUID()))) { + if (fields.size() > 0) + ans.add(extractFields(oSS,fields)); + else + ans.add(oSS); + } + } + //TODO: apply pagination to results + return Response.status(200).entity( + new NeutronFloatingIPRequest(ans)).build(); + } + + /** + * Returns a specific FloatingIP */ + + @Path("{floatingipUUID}") + @GET + @Produces({ MediaType.APPLICATION_JSON }) + @StatusCodes({ + @ResponseCode(code = 200, condition = "Operation successful"), + @ResponseCode(code = 401, condition = "Unauthorized"), + @ResponseCode(code = 404, condition = "Not Found"), + @ResponseCode(code = 501, condition = "Not Implemented") }) + public Response showFloatingIP( + @PathParam("floatingipUUID") String floatingipUUID, + // return fields + @QueryParam("fields") List fields ) { + INeutronFloatingIPCRUD floatingIPInterface = NeutronNBInterfaces.getIfNBFloatingIPCRUD("default",this); + if (floatingIPInterface == null) { + throw new ServiceUnavailableException("Floating IP CRUD Interface " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + if (!floatingIPInterface.floatingIPExists(floatingipUUID)) + return Response.status(404).build(); + if (fields.size() > 0) { + NeutronFloatingIP ans = floatingIPInterface.getFloatingIP(floatingipUUID); + return Response.status(200).entity( + new NeutronFloatingIPRequest(extractFields(ans, fields))).build(); + } else + return Response.status(200).entity( + new NeutronFloatingIPRequest(floatingIPInterface.getFloatingIP(floatingipUUID))).build(); + + } + + /** + * Creates new FloatingIPs */ + + @POST + @Produces({ MediaType.APPLICATION_JSON }) + @Consumes({ MediaType.APPLICATION_JSON }) + @StatusCodes({ + @ResponseCode(code = 201, condition = "Created"), + @ResponseCode(code = 400, condition = "Bad Request"), + @ResponseCode(code = 401, condition = "Unauthorized"), + @ResponseCode(code = 409, condition = "Conflict"), + @ResponseCode(code = 501, condition = "Not Implemented") }) + public Response createFloatingIPs(final NeutronFloatingIPRequest input) { + INeutronFloatingIPCRUD floatingIPInterface = NeutronNBInterfaces.getIfNBFloatingIPCRUD("default",this); + if (floatingIPInterface == null) { + throw new ServiceUnavailableException("Floating IP CRUD Interface " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + INeutronNetworkCRUD networkInterface = NeutronNBInterfaces.getIfNBNetworkCRUD("default", this); + if (networkInterface == null) { + throw new ServiceUnavailableException("Network CRUD Interface " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + INeutronSubnetCRUD subnetInterface = NeutronNBInterfaces.getIfNBSubnetCRUD("default", this); + if (subnetInterface == null) { + throw new ServiceUnavailableException("Subnet CRUD Interface " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + INeutronPortCRUD portInterface = NeutronNBInterfaces.getIfNBPortCRUD("default", this); + if (portInterface == null) { + throw new ServiceUnavailableException("Port CRUD Interface " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + if (input.isSingleton()) { + NeutronFloatingIP singleton = input.getSingleton(); + // check existence of id in cache and return badrequest if exists + if (floatingIPInterface.floatingIPExists(singleton.getID())) + return Response.status(400).build(); + // check if the external network is specified, exists, and is an external network + String externalNetworkUUID = singleton.getFloatingNetworkUUID(); + if (externalNetworkUUID == null) + return Response.status(400).build(); + if (!networkInterface.networkExists(externalNetworkUUID)) + return Response.status(400).build(); + NeutronNetwork externNetwork = networkInterface.getNetwork(externalNetworkUUID); + if (!externNetwork.isRouterExternal()) + return Response.status(400).build(); + // if floating IP is specified, make sure it can come from the network + String floatingIP = singleton.getFloatingIPAddress(); + if (floatingIP != null) { + if (externNetwork.getSubnets().size() > 1) + return Response.status(400).build(); + NeutronSubnet externSubnet = subnetInterface.getSubnet(externNetwork.getSubnets().get(0)); + if (!externSubnet.isValidIP(floatingIP)) + return Response.status(400).build(); + if (externSubnet.isIPInUse(floatingIP)) + return Response.status(409).build(); + } + // if port_id is specified, then check that the port exists and has at least one IP + String port_id = singleton.getPortUUID(); + if (port_id != null) { + String fixedIP = null; // used for the fixedIP calculation + if (!portInterface.portExists(port_id)) + return Response.status(404).build(); + NeutronPort port = portInterface.getPort(port_id); + if (port.getFixedIPs().size() < 1) + return Response.status(400).build(); + // if there is more than one fixed IP then check for fixed_ip_address + // and that it is in the list of port addresses + if (port.getFixedIPs().size() > 1) { + fixedIP = singleton.getFixedIPAddress(); + if (fixedIP == null) + return Response.status(400).build(); + Iterator i = port.getFixedIPs().iterator(); + boolean validFixedIP = false; + while (i.hasNext() && !validFixedIP) { + Neutron_IPs ip = i.next(); + if (ip.getIpAddress().equals(fixedIP)) + validFixedIP = true; + } + if (!validFixedIP) + return Response.status(400).build(); + } else { + fixedIP = port.getFixedIPs().get(0).getIpAddress(); + if (singleton.getFixedIPAddress() != null && !fixedIP.equalsIgnoreCase(singleton.getFixedIPAddress())) + return Response.status(400).build(); + } + //lastly check that this fixed IP address isn't already used + if (port.isBoundToFloatingIP(fixedIP)) + return Response.status(409).build(); + singleton.setFixedIPAddress(fixedIP); + } + Object[] instances = ServiceHelper.getGlobalInstances(INeutronFloatingIPAware.class, this, null); + if (instances != null) { + for (Object instance : instances) { + INeutronFloatingIPAware service = (INeutronFloatingIPAware) instance; + int status = service.canCreateFloatingIP(singleton); + if (status < 200 || status > 299) + return Response.status(status).build(); + } + } + floatingIPInterface.addFloatingIP(singleton); + if (instances != null) { + for (Object instance : instances) { + INeutronFloatingIPAware service = (INeutronFloatingIPAware) instance; + service.neutronFloatingIPCreated(singleton); + } + } + } else { + return Response.status(400).build(); + } + return Response.status(201).entity(input).build(); + } + + /** + * Updates a FloatingIP */ + + @Path("{floatingipUUID}") + @PUT + @Produces({ MediaType.APPLICATION_JSON }) + @Consumes({ MediaType.APPLICATION_JSON }) + @StatusCodes({ + @ResponseCode(code = 200, condition = "Operation successful"), + @ResponseCode(code = 400, condition = "Bad Request"), + @ResponseCode(code = 401, condition = "Unauthorized"), + @ResponseCode(code = 404, condition = "Not Found"), + @ResponseCode(code = 409, condition = "Conflict"), + @ResponseCode(code = 501, condition = "Not Implemented") }) + public Response updateFloatingIP( + @PathParam("floatingipUUID") String floatingipUUID, + NeutronFloatingIPRequest input + ) { + INeutronFloatingIPCRUD floatingIPInterface = NeutronNBInterfaces.getIfNBFloatingIPCRUD("default",this); + if (floatingIPInterface == null) { + throw new ServiceUnavailableException("Floating IP CRUD Interface " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + INeutronNetworkCRUD networkInterface = NeutronNBInterfaces.getIfNBNetworkCRUD("default", this); + if (networkInterface == null) { + throw new ServiceUnavailableException("Network CRUD Interface " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + INeutronSubnetCRUD subnetInterface = NeutronNBInterfaces.getIfNBSubnetCRUD("default", this); + if (subnetInterface == null) { + throw new ServiceUnavailableException("Subnet CRUD Interface " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + INeutronPortCRUD portInterface = NeutronNBInterfaces.getIfNBPortCRUD("default", this); + if (portInterface == null) { + throw new ServiceUnavailableException("Port CRUD Interface " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + if (!floatingIPInterface.floatingIPExists(floatingipUUID)) + return Response.status(404).build(); + + NeutronFloatingIP sourceFloatingIP = floatingIPInterface.getFloatingIP(floatingipUUID); + if (!input.isSingleton()) + return Response.status(400).build(); + NeutronFloatingIP singleton = input.getSingleton(); + if (singleton.getID() != null) + return Response.status(400).build(); + + NeutronNetwork externNetwork = networkInterface.getNetwork( + sourceFloatingIP.getFloatingNetworkUUID()); + + // if floating IP is specified, make sure it can come from the network + String floatingIP = singleton.getFloatingIPAddress(); + if (floatingIP != null) { + if (externNetwork.getSubnets().size() > 1) + return Response.status(400).build(); + NeutronSubnet externSubnet = subnetInterface.getSubnet(externNetwork.getSubnets().get(0)); + if (!externSubnet.isValidIP(floatingIP)) + return Response.status(400).build(); + if (externSubnet.isIPInUse(floatingIP)) + return Response.status(409).build(); + } + + // if port_id is specified, then check that the port exists and has at least one IP + String port_id = singleton.getPortUUID(); + if (port_id != null) { + String fixedIP = null; // used for the fixedIP calculation + if (!portInterface.portExists(port_id)) + return Response.status(404).build(); + NeutronPort port = portInterface.getPort(port_id); + if (port.getFixedIPs().size() < 1) + return Response.status(400).build(); + // if there is more than one fixed IP then check for fixed_ip_address + // and that it is in the list of port addresses + if (port.getFixedIPs().size() > 1) { + fixedIP = singleton.getFixedIPAddress(); + if (fixedIP == null) + return Response.status(400).build(); + Iterator i = port.getFixedIPs().iterator(); + boolean validFixedIP = false; + while (i.hasNext() && !validFixedIP) { + Neutron_IPs ip = i.next(); + if (ip.getIpAddress().equals(fixedIP)) + validFixedIP = true; + } + if (!validFixedIP) + return Response.status(400).build(); + } else { + fixedIP = port.getFixedIPs().get(0).getIpAddress(); + if (singleton.getFixedIPAddress() != null && + !fixedIP.equalsIgnoreCase(singleton.getFixedIPAddress())) + return Response.status(400).build(); + } + //lastly check that this fixed IP address isn't already used + if (port.isBoundToFloatingIP(fixedIP)) + return Response.status(409).build(); + singleton.setFixedIPAddress(fixedIP); + } + NeutronFloatingIP target = floatingIPInterface.getFloatingIP(floatingipUUID); + Object[] instances = ServiceHelper.getGlobalInstances(INeutronFloatingIPAware.class, this, null); + if (instances != null) { + for (Object instance : instances) { + INeutronFloatingIPAware service = (INeutronFloatingIPAware) instance; + int status = service.canUpdateFloatingIP(singleton, target); + if (status < 200 || status > 299) + return Response.status(status).build(); + } + } + floatingIPInterface.updateFloatingIP(floatingipUUID, singleton); + target = floatingIPInterface.getFloatingIP(floatingipUUID); + if (instances != null) { + for (Object instance : instances) { + INeutronFloatingIPAware service = (INeutronFloatingIPAware) instance; + service.neutronFloatingIPUpdated(target); + } + } + return Response.status(200).entity( + new NeutronFloatingIPRequest(target)).build(); + + } + + /** + * Deletes a FloatingIP */ + + @Path("{floatingipUUID}") + @DELETE + @StatusCodes({ + @ResponseCode(code = 204, condition = "No Content"), + @ResponseCode(code = 401, condition = "Unauthorized"), + @ResponseCode(code = 404, condition = "Not Found"), + @ResponseCode(code = 501, condition = "Not Implemented") }) + public Response deleteFloatingIP( + @PathParam("floatingipUUID") String floatingipUUID) { + INeutronFloatingIPCRUD floatingIPInterface = NeutronNBInterfaces.getIfNBFloatingIPCRUD("default",this); + if (floatingIPInterface == null) { + throw new ServiceUnavailableException("Floating IP CRUD Interface " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + if (!floatingIPInterface.floatingIPExists(floatingipUUID)) + return Response.status(404).build(); + // TODO: need to undo port association if it exists + NeutronFloatingIP singleton = floatingIPInterface.getFloatingIP(floatingipUUID); + Object[] instances = ServiceHelper.getGlobalInstances(INeutronFloatingIPAware.class, this, null); + if (instances != null) { + for (Object instance : instances) { + INeutronFloatingIPAware service = (INeutronFloatingIPAware) instance; + int status = service.canDeleteFloatingIP(singleton); + if (status < 200 || status > 299) + return Response.status(status).build(); + } + } + floatingIPInterface.removeFloatingIP(floatingipUUID); + if (instances != null) { + for (Object instance : instances) { + INeutronFloatingIPAware service = (INeutronFloatingIPAware) instance; + service.neutronFloatingIPDeleted(singleton); + } + } + return Response.status(204).build(); + } +} diff --git a/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronNBInterfaces.java b/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronNBInterfaces.java new file mode 100644 index 0000000000..730fe2c3b7 --- /dev/null +++ b/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronNBInterfaces.java @@ -0,0 +1,193 @@ +/* + * Copyright IBM Corporation, 2013. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.networkconfig.neutron.northbound; + +import java.util.List; + +import org.opendaylight.controller.containermanager.IContainerManager; +import org.opendaylight.controller.networkconfig.neutron.INeutronFloatingIPCRUD; +import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD; +import org.opendaylight.controller.networkconfig.neutron.INeutronPortCRUD; +import org.opendaylight.controller.networkconfig.neutron.INeutronRouterCRUD; +import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD; +import org.opendaylight.controller.networkconfig.neutron.NeutronCRUDInterfaces; +import org.opendaylight.controller.northbound.commons.RestMessages; +import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException; +import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException; +import org.opendaylight.controller.sal.utils.ServiceHelper; + +public class NeutronNBInterfaces { + + // return a class that implements the IfNBNetworkCRUD interface + static INeutronNetworkCRUD getIfNBNetworkCRUD(String containerName, Object o) { + /* IContainerManager containerManager = (IContainerManager) ServiceHelper + .getGlobalInstance(IContainerManager.class, o); + if (containerManager == null) { + throw new ServiceUnavailableException("Container " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + + boolean found = false; + List containerNames = containerManager.getContainerNames(); + for (String cName : containerNames) { + if (cName.trim().equalsIgnoreCase(containerName.trim())) { + found = true; + } + } + + if (found == false) { + throw new ResourceNotFoundException(containerName + " " + + RestMessages.NOCONTAINER.toString()); + } + + IfNBNetworkCRUD answer = (IfNBNetworkCRUD) ServiceHelper.getInstance( + IfNBNetworkCRUD.class, containerName, o); */ + + INeutronNetworkCRUD answer = NeutronCRUDInterfaces.getINeutronNetworkCRUD(o); + + if (answer == null) { + throw new ServiceUnavailableException("Network CRUD Service " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + + return answer; + } + + // return a class that implements the IfNBSubnetCRUD interface + static INeutronSubnetCRUD getIfNBSubnetCRUD(String containerName, Object o) { + IContainerManager containerManager = (IContainerManager) ServiceHelper + .getGlobalInstance(IContainerManager.class, o); + if (containerManager == null) { + throw new ServiceUnavailableException("Container " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + + boolean found = false; + List containerNames = containerManager.getContainerNames(); + for (String cName : containerNames) { + if (cName.trim().equalsIgnoreCase(containerName.trim())) { + found = true; + } + } + + if (found == false) { + throw new ResourceNotFoundException(containerName + " " + + RestMessages.NOCONTAINER.toString()); + } + + INeutronSubnetCRUD answer = (INeutronSubnetCRUD) ServiceHelper.getInstance( + INeutronSubnetCRUD.class, containerName, o); + + if (answer == null) { + throw new ServiceUnavailableException("Network CRUD Service " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + + return answer; + } + + // return a class that implements the IfNBPortCRUD interface + static INeutronPortCRUD getIfNBPortCRUD(String containerName, Object o) { + IContainerManager containerManager = (IContainerManager) ServiceHelper + .getGlobalInstance(IContainerManager.class, o); + if (containerManager == null) { + throw new ServiceUnavailableException("Container " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + + boolean found = false; + List containerNames = containerManager.getContainerNames(); + for (String cName : containerNames) { + if (cName.trim().equalsIgnoreCase(containerName.trim())) { + found = true; + } + } + + if (found == false) { + throw new ResourceNotFoundException(containerName + " " + + RestMessages.NOCONTAINER.toString()); + } + + INeutronPortCRUD answer = (INeutronPortCRUD) ServiceHelper.getInstance( + INeutronPortCRUD.class, containerName, o); + + if (answer == null) { + throw new ServiceUnavailableException("Network CRUD Service " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + + return answer; + } + + // return a class that implements the IfNBRouterCRUD interface + static INeutronRouterCRUD getIfNBRouterCRUD(String containerName, Object o) { + IContainerManager containerManager = (IContainerManager) ServiceHelper + .getGlobalInstance(IContainerManager.class, o); + if (containerManager == null) { + throw new ServiceUnavailableException("Container " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + + boolean found = false; + List containerNames = containerManager.getContainerNames(); + for (String cName : containerNames) { + if (cName.trim().equalsIgnoreCase(containerName.trim())) { + found = true; + } + } + + if (found == false) { + throw new ResourceNotFoundException(containerName + " " + + RestMessages.NOCONTAINER.toString()); + } + + INeutronRouterCRUD answer = (INeutronRouterCRUD) ServiceHelper.getInstance( + INeutronRouterCRUD.class, containerName, o); + + if (answer == null) { + throw new ServiceUnavailableException("Network CRUD Service " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + + return answer; + } + + // return a class that implements the IfNBFloatingIPCRUD interface + static INeutronFloatingIPCRUD getIfNBFloatingIPCRUD(String containerName, Object o) { + IContainerManager containerManager = (IContainerManager) ServiceHelper + .getGlobalInstance(IContainerManager.class, o); + if (containerManager == null) { + throw new ServiceUnavailableException("Container " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + + boolean found = false; + List containerNames = containerManager.getContainerNames(); + for (String cName : containerNames) { + if (cName.trim().equalsIgnoreCase(containerName.trim())) { + found = true; + } + } + + if (found == false) { + throw new ResourceNotFoundException(containerName + " " + + RestMessages.NOCONTAINER.toString()); + } + + INeutronFloatingIPCRUD answer = (INeutronFloatingIPCRUD) ServiceHelper.getInstance( + INeutronFloatingIPCRUD.class, containerName, o); + + if (answer == null) { + throw new ServiceUnavailableException("Network CRUD Service " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + + return answer; + } +} diff --git a/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronNetworkRequest.java b/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronNetworkRequest.java new file mode 100644 index 0000000000..9d449380a5 --- /dev/null +++ b/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronNetworkRequest.java @@ -0,0 +1,55 @@ +/* + * Copyright IBM Corporation, 2013. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.networkconfig.neutron.northbound; + +import java.util.List; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork; + +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) +public class NeutronNetworkRequest { + // See OpenStack Network API v2.0 Reference for description of + // annotated attributes + + @XmlElement(name="network") + NeutronNetwork singletonNetwork; + + @XmlElement(name="networks") + List bulkRequest; + + NeutronNetworkRequest() { + } + + NeutronNetworkRequest(List bulk) { + bulkRequest = bulk; + singletonNetwork = null; + } + + NeutronNetworkRequest(NeutronNetwork net) { + singletonNetwork = net; + } + + public NeutronNetwork getSingleton() { + return singletonNetwork; + } + + public boolean isSingleton() { + return (singletonNetwork != null); + } + + public List getBulk() { + return bulkRequest; + } +} diff --git a/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronNetworksNorthbound.java b/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronNetworksNorthbound.java new file mode 100644 index 0000000000..2505da62cf --- /dev/null +++ b/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronNetworksNorthbound.java @@ -0,0 +1,355 @@ +/* + * Copyright IBM Corporation, 2013. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.networkconfig.neutron.northbound; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import org.codehaus.enunciate.jaxrs.ResponseCode; +import org.codehaus.enunciate.jaxrs.StatusCodes; +import org.codehaus.enunciate.jaxrs.TypeHint; +import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkAware; +import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD; +import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork; +import org.opendaylight.controller.northbound.commons.RestMessages; +import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException; +import org.opendaylight.controller.sal.utils.ServiceHelper; + +/** + * Open DOVE Northbound REST APIs for Network.
+ * This class provides REST APIs for managing open DOVE internals related to Networks + * + *
+ *
+ * Authentication scheme : HTTP Basic
+ * Authentication realm : opendaylight
+ * Transport : HTTP and HTTPS
+ *
+ * HTTPS Authentication is disabled by default. Administrator can enable it in + * tomcat-server.xml after adding a proper keystore / SSL certificate from a + * trusted authority.
+ * More info : + * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration + * + */ + +@Path("/networks") +public class NeutronNetworksNorthbound { + + private NeutronNetwork extractFields(NeutronNetwork o, List fields) { + return o.extractFields(fields); + } + + /** + * Returns a list of all Networks */ + + @GET + @Produces({ MediaType.APPLICATION_JSON }) + //@TypeHint(OpenStackNetworks.class) + @StatusCodes({ + @ResponseCode(code = 200, condition = "Operation successful"), + @ResponseCode(code = 401, condition = "Unauthorized") }) + public Response listNetworks( + // return fields + @QueryParam("fields") List fields, + // note: openstack isn't clear about filtering on lists, so we aren't handling them + @QueryParam("id") String queryID, + @QueryParam("name") String queryName, + @QueryParam("admin_state_up") String queryAdminStateUp, + @QueryParam("status") String queryStatus, + @QueryParam("shared") String queryShared, + @QueryParam("tenant_id") String queryTenantID, + @QueryParam("router_external") String queryRouterExternal, + @QueryParam("provider_network_type") String queryProviderNetworkType, + @QueryParam("provider_physical_network") String queryProviderPhysicalNetwork, + @QueryParam("provider_segmentation_id") String queryProviderSegmentationID, + // pagination + @QueryParam("limit") String limit, + @QueryParam("marker") String marker, + @QueryParam("page_reverse") String pageReverse + // sorting not supported + ) { + INeutronNetworkCRUD networkInterface = NeutronNBInterfaces.getIfNBNetworkCRUD("default", this); + if (networkInterface == null) { + throw new ServiceUnavailableException("Network CRUD Interface " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + List allNetworks = networkInterface.getAllNetworks(); + List ans = new ArrayList(); + Iterator i = allNetworks.iterator(); + while (i.hasNext()) { + NeutronNetwork oSN = i.next(); + //match filters: TODO provider extension + Boolean bAdminStateUp = null; + Boolean bShared = null; + Boolean bRouterExternal = null; + if (queryAdminStateUp != null) + bAdminStateUp = new Boolean(queryAdminStateUp); + if (queryShared != null) + bShared = new Boolean(queryShared); + if (queryRouterExternal != null) + bRouterExternal = new Boolean(queryRouterExternal); + if ((queryID == null || queryID.equals(oSN.getID())) && + (queryName == null || queryName.equals(oSN.getNetworkName())) && + (bAdminStateUp == null || bAdminStateUp.booleanValue() == oSN.isAdminStateUp()) && + (queryStatus == null || queryStatus.equals(oSN.getStatus())) && + (bShared == null || bShared.booleanValue() == oSN.isShared()) && + (bRouterExternal == null || bRouterExternal.booleanValue() == oSN.isRouterExternal()) && + (queryTenantID == null || queryTenantID.equals(oSN.getTenantID()))) { + if (fields.size() > 0) + ans.add(extractFields(oSN,fields)); + else + ans.add(oSN); + } + } + //TODO: apply pagination to results + return Response.status(200).entity( + new NeutronNetworkRequest(ans)).build(); + } + + /** + * Returns a specific Network */ + + @Path("{netUUID}") + @GET + @Produces({ MediaType.APPLICATION_JSON }) + //@TypeHint(OpenStackNetworks.class) + @StatusCodes({ + @ResponseCode(code = 200, condition = "Operation successful"), + @ResponseCode(code = 401, condition = "Unauthorized"), + @ResponseCode(code = 404, condition = "Not Found") }) + public Response showNetwork( + @PathParam("netUUID") String netUUID, + // return fields + @QueryParam("fields") List fields + ) { + INeutronNetworkCRUD networkInterface = NeutronNBInterfaces.getIfNBNetworkCRUD("default", this); + if (networkInterface == null) { + throw new ServiceUnavailableException("Network CRUD Interface " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + if (!networkInterface.networkExists(netUUID)) + return Response.status(404).build(); + if (fields.size() > 0) { + NeutronNetwork ans = networkInterface.getNetwork(netUUID); + return Response.status(200).entity( + new NeutronNetworkRequest(extractFields(ans, fields))).build(); + } else + return Response.status(200).entity( + new NeutronNetworkRequest(networkInterface.getNetwork(netUUID))).build(); + } + + /** + * Creates new Networks */ + @POST + @Produces({ MediaType.APPLICATION_JSON }) + @Consumes({ MediaType.APPLICATION_JSON }) + @TypeHint(NeutronNetwork.class) + @StatusCodes({ + @ResponseCode(code = 201, condition = "Created"), + @ResponseCode(code = 400, condition = "Bad Request"), + @ResponseCode(code = 401, condition = "Unauthorized") }) + public Response createNetworks(final NeutronNetworkRequest input) { + INeutronNetworkCRUD networkInterface = NeutronNBInterfaces.getIfNBNetworkCRUD("default", this); + if (networkInterface == null) { + throw new ServiceUnavailableException("Network CRUD Interface " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + if (input.isSingleton()) { + NeutronNetwork singleton = input.getSingleton(); + + /* + * network ID can't already exist + */ + if (networkInterface.networkExists(singleton.getID())) + return Response.status(400).build(); + + Object[] instances = ServiceHelper.getGlobalInstances(INeutronNetworkAware.class, this, null); + if (instances != null) { + for (Object instance : instances) { + INeutronNetworkAware service = (INeutronNetworkAware) instance; + int status = service.canCreateNetwork(singleton); + if (status < 200 || status > 299) + return Response.status(status).build(); + } + } + + // add network to cache + networkInterface.addNetwork(singleton); + if (instances != null) { + for (Object instance : instances) { + INeutronNetworkAware service = (INeutronNetworkAware) instance; + service.neutronNetworkCreated(singleton); + } + } + + } else { + List bulk = input.getBulk(); + Iterator i = bulk.iterator(); + HashMap testMap = new HashMap(); + Object[] instances = ServiceHelper.getGlobalInstances(INeutronNetworkAware.class, this, null); + while (i.hasNext()) { + NeutronNetwork test = i.next(); + + /* + * network ID can't already exist, nor can there be an entry for this UUID + * already in this bulk request + */ + if (networkInterface.networkExists(test.getID())) + return Response.status(400).build(); + if (testMap.containsKey(test.getID())) + return Response.status(400).build(); + if (instances != null) { + for (Object instance: instances) { + INeutronNetworkAware service = (INeutronNetworkAware) instance; + int status = service.canCreateNetwork(test); + if (status < 200 || status > 299) + return Response.status(status).build(); + } + } + testMap.put(test.getID(),test); + } + + // now that everything passed, add items to the cache + i = bulk.iterator(); + while (i.hasNext()) { + NeutronNetwork test = i.next(); + test.initDefaults(); + networkInterface.addNetwork(test); + if (instances != null) { + for (Object instance: instances) { + INeutronNetworkAware service = (INeutronNetworkAware) instance; + service.neutronNetworkCreated(test); + } + } + } + } + return Response.status(201).entity(input).build(); + } + + /** + * Updates a Network */ + @Path("{netUUID}") + @PUT + @Produces({ MediaType.APPLICATION_JSON }) + @Consumes({ MediaType.APPLICATION_JSON }) + //@TypeHint(OpenStackNetworks.class) + @StatusCodes({ + @ResponseCode(code = 200, condition = "Operation successful"), + @ResponseCode(code = 400, condition = "Bad Request"), + @ResponseCode(code = 403, condition = "Forbidden"), + @ResponseCode(code = 404, condition = "Not Found"), }) + public Response updateNetwork( + @PathParam("netUUID") String netUUID, final NeutronNetworkRequest input + ) { + INeutronNetworkCRUD networkInterface = NeutronNBInterfaces.getIfNBNetworkCRUD("default", this); + if (networkInterface == null) { + throw new ServiceUnavailableException("Network CRUD Interface " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + + /* + * network has to exist and only a single delta is supported + */ + if (!networkInterface.networkExists(netUUID)) + return Response.status(404).build(); + if (!input.isSingleton()) + return Response.status(400).build(); + NeutronNetwork delta = input.getSingleton(); + + /* + * transitions forbidden by Neutron + */ + if (delta.getID() != null || delta.getTenantID() != null || + delta.getStatus() != null) + return Response.status(400).build(); + + Object[] instances = ServiceHelper.getGlobalInstances(INeutronNetworkAware.class, this, null); + if (instances != null) { + for (Object instance : instances) { + INeutronNetworkAware service = (INeutronNetworkAware) instance; + NeutronNetwork original = networkInterface.getNetwork(netUUID); + int status = service.canUpdateNetwork(delta, original); + if (status < 200 || status > 299) + return Response.status(status).build(); + } + } + + // update network object and return the modified object + networkInterface.updateNetwork(netUUID, delta); + NeutronNetwork updatedSingleton = networkInterface.getNetwork(netUUID); + if (instances != null) { + for (Object instance : instances) { + INeutronNetworkAware service = (INeutronNetworkAware) instance; + service.neutronNetworkUpdated(updatedSingleton); + } + } + return Response.status(200).entity( + new NeutronNetworkRequest(networkInterface.getNetwork(netUUID))).build(); + } + + /** + * Deletes a Network */ + + @Path("{netUUID}") + @DELETE + @StatusCodes({ + @ResponseCode(code = 204, condition = "No Content"), + @ResponseCode(code = 401, condition = "Unauthorized"), + @ResponseCode(code = 404, condition = "Not Found"), + @ResponseCode(code = 409, condition = "Network In Use") }) + public Response deleteNetwork( + @PathParam("netUUID") String netUUID) { + INeutronNetworkCRUD networkInterface = NeutronNBInterfaces.getIfNBNetworkCRUD("default", this); + if (networkInterface == null) { + throw new ServiceUnavailableException("Network CRUD Interface " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + + /* + * network has to exist and not be in use before it can be removed + */ + if (!networkInterface.networkExists(netUUID)) + return Response.status(404).build(); + if (networkInterface.networkInUse(netUUID)) + return Response.status(409).build(); + + NeutronNetwork singleton = networkInterface.getNetwork(netUUID); + Object[] instances = ServiceHelper.getGlobalInstances(INeutronNetworkAware.class, this, null); + if (instances != null) { + for (Object instance : instances) { + INeutronNetworkAware service = (INeutronNetworkAware) instance; + int status = service.canDeleteNetwork(singleton); + if (status < 200 || status > 299) + return Response.status(status).build(); + } + } + networkInterface.removeNetwork(netUUID); + if (instances != null) { + for (Object instance : instances) { + INeutronNetworkAware service = (INeutronNetworkAware) instance; + service.neutronNetworkDeleted(singleton); + } + } + return Response.status(204).build(); + } +} diff --git a/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronNorthboundRSApplication.java b/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronNorthboundRSApplication.java new file mode 100644 index 0000000000..020104f957 --- /dev/null +++ b/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronNorthboundRSApplication.java @@ -0,0 +1,63 @@ +/* + * Copyright IBM Corporation, 2013. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.networkconfig.neutron.northbound; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import javax.ws.rs.core.Application; +import org.eclipse.persistence.jaxb.rs.MOXyJsonProvider; +import org.opendaylight.controller.networkconfig.neutron.northbound.NeutronFloatingIPsNorthbound; +import org.opendaylight.controller.networkconfig.neutron.northbound.NeutronNetworksNorthbound; +import org.opendaylight.controller.networkconfig.neutron.northbound.NeutronPortsNorthbound; +import org.opendaylight.controller.networkconfig.neutron.northbound.NeutronRoutersNorthbound; +import org.opendaylight.controller.networkconfig.neutron.northbound.NeutronSubnetsNorthbound; + + +/** + * This class is an instance of javax.ws.rs.core.Application and is used to return the classes + * that will be instantiated for JAXRS processing. This is necessary + * because package scanning in jersey doesn't yet work in OSGi environment. + * + */ +public class NeutronNorthboundRSApplication extends Application { + @Override + public Set> getClasses() { + Set> classes = new HashSet>(); +// northbound URIs + classes.add(NeutronNetworksNorthbound.class); + classes.add(NeutronSubnetsNorthbound.class); + classes.add(NeutronPortsNorthbound.class); + classes.add(NeutronRoutersNorthbound.class); + classes.add(NeutronFloatingIPsNorthbound.class); + return classes; + } + + @Override + public Set getSingletons() { + MOXyJsonProvider moxyJsonProvider = new MOXyJsonProvider(); + + moxyJsonProvider.setAttributePrefix("@"); + moxyJsonProvider.setFormattedOutput(true); + moxyJsonProvider.setIncludeRoot(false); + moxyJsonProvider.setMarshalEmptyCollections(true); + moxyJsonProvider.setValueWrapper("$"); + + Map namespacePrefixMapper = new HashMap(1); + namespacePrefixMapper.put("router", "router"); // FIXME: fill in with XSD + namespacePrefixMapper.put("provider", "provider"); // FIXME: fill in with XSD + moxyJsonProvider.setNamespacePrefixMapper(namespacePrefixMapper); + moxyJsonProvider.setNamespaceSeparator(':'); + + HashSet set = new HashSet(1); + set.add(moxyJsonProvider); + return set; + } +} diff --git a/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronPortRequest.java b/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronPortRequest.java new file mode 100644 index 0000000000..f6765fb221 --- /dev/null +++ b/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronPortRequest.java @@ -0,0 +1,55 @@ +/* + * Copyright IBM Corporation, 2013. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.networkconfig.neutron.northbound; + +import java.util.List; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +import org.opendaylight.controller.networkconfig.neutron.NeutronPort; + +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) +public class NeutronPortRequest { + // See OpenStack Network API v2.0 Reference for description of + // annotated attributes + + @XmlElement(name="port") + NeutronPort singletonPort; + + @XmlElement(name="ports") + List bulkRequest; + + NeutronPortRequest() { + } + + NeutronPortRequest(List bulk) { + bulkRequest = bulk; + singletonPort = null; + } + + NeutronPortRequest(NeutronPort port) { + singletonPort = port; + } + + public NeutronPort getSingleton() { + return singletonPort; + } + + public boolean isSingleton() { + return (singletonPort != null); + } + + public List getBulk() { + return bulkRequest; + } +} diff --git a/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronPortsNorthbound.java b/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronPortsNorthbound.java new file mode 100644 index 0000000000..78646a6383 --- /dev/null +++ b/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronPortsNorthbound.java @@ -0,0 +1,476 @@ +/* + * Copyright IBM Corporation, 2013. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.networkconfig.neutron.northbound; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import org.codehaus.enunciate.jaxrs.ResponseCode; +import org.codehaus.enunciate.jaxrs.StatusCodes; +import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD; +import org.opendaylight.controller.networkconfig.neutron.INeutronPortAware; +import org.opendaylight.controller.networkconfig.neutron.INeutronPortCRUD; +import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetAware; +import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD; +import org.opendaylight.controller.networkconfig.neutron.NeutronPort; +import org.opendaylight.controller.networkconfig.neutron.NeutronSubnet; +import org.opendaylight.controller.networkconfig.neutron.Neutron_IPs; +import org.opendaylight.controller.northbound.commons.RestMessages; +import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException; +import org.opendaylight.controller.sal.utils.ServiceHelper; + +/** + * Open DOVE Northbound REST APIs.
+ * This class provides REST APIs for managing the open DOVE + * + *
+ *
+ * Authentication scheme : HTTP Basic
+ * Authentication realm : opendaylight
+ * Transport : HTTP and HTTPS
+ *
+ * HTTPS Authentication is disabled by default. Administrator can enable it in + * tomcat-server.xml after adding a proper keystore / SSL certificate from a + * trusted authority.
+ * More info : + * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration + * + */ + +@Path("/ports") +public class NeutronPortsNorthbound { + + private NeutronPort extractFields(NeutronPort o, List fields) { + return o.extractFields(fields); + } + + /** + * Returns a list of all Ports */ + + @GET + @Produces({ MediaType.APPLICATION_JSON }) + //@TypeHint(OpenStackPorts.class) + @StatusCodes({ + @ResponseCode(code = 200, condition = "Operation successful"), + @ResponseCode(code = 401, condition = "Unauthorized"), + @ResponseCode(code = 501, condition = "Not Implemented") }) + public Response listPorts( + // return fields + @QueryParam("fields") List fields, + // note: openstack isn't clear about filtering on lists, so we aren't handling them + @QueryParam("id") String queryID, + @QueryParam("network_id") String queryNetworkID, + @QueryParam("name") String queryName, + @QueryParam("admin_state_up") String queryAdminStateUp, + @QueryParam("status") String queryStatus, + @QueryParam("mac_address") String queryMACAddress, + @QueryParam("device_id") String queryDeviceID, + @QueryParam("device_owner") String queryDeviceOwner, + @QueryParam("tenant_id") String queryTenantID, + // pagination + @QueryParam("limit") String limit, + @QueryParam("marker") String marker, + @QueryParam("page_reverse") String pageReverse + // sorting not supported + ) { + INeutronPortCRUD portInterface = NeutronNBInterfaces.getIfNBPortCRUD("default",this); + if (portInterface == null) { + throw new ServiceUnavailableException("Port CRUD Interface " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + List allPorts = portInterface.getAllPorts(); + List ans = new ArrayList(); + Iterator i = allPorts.iterator(); + while (i.hasNext()) { + NeutronPort oSS = i.next(); + if ((queryID == null || queryID.equals(oSS.getID())) && + (queryNetworkID == null || queryNetworkID.equals(oSS.getNetworkUUID())) && + (queryName == null || queryName.equals(oSS.getName())) && + (queryAdminStateUp == null || queryAdminStateUp.equals(oSS.getAdminStateUp())) && + (queryStatus == null || queryStatus.equals(oSS.getStatus())) && + (queryMACAddress == null || queryMACAddress.equals(oSS.getMacAddress())) && + (queryDeviceID == null || queryDeviceID.equals(oSS.getDeviceID())) && + (queryDeviceOwner == null || queryDeviceOwner.equals(oSS.getDeviceOwner())) && + (queryTenantID == null || queryTenantID.equals(oSS.getTenantID()))) { + if (fields.size() > 0) + ans.add(extractFields(oSS,fields)); + else + ans.add(oSS); + } + } + //TODO: apply pagination to results + return Response.status(200).entity( + new NeutronPortRequest(ans)).build(); + } + + /** + * Returns a specific Port */ + + @Path("{portUUID}") + @GET + @Produces({ MediaType.APPLICATION_JSON }) + //@TypeHint(OpenStackPorts.class) + @StatusCodes({ + @ResponseCode(code = 200, condition = "Operation successful"), + @ResponseCode(code = 401, condition = "Unauthorized"), + @ResponseCode(code = 404, condition = "Not Found"), + @ResponseCode(code = 501, condition = "Not Implemented") }) + public Response showPort( + @PathParam("portUUID") String portUUID, + // return fields + @QueryParam("fields") List fields ) { + INeutronPortCRUD portInterface = NeutronNBInterfaces.getIfNBPortCRUD("default",this); + if (portInterface == null) { + throw new ServiceUnavailableException("Port CRUD Interface " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + if (!portInterface.portExists(portUUID)) + return Response.status(404).build(); + if (fields.size() > 0) { + NeutronPort ans = portInterface.getPort(portUUID); + return Response.status(200).entity( + new NeutronPortRequest(extractFields(ans, fields))).build(); + } else + return Response.status(200).entity( + new NeutronPortRequest(portInterface.getPort(portUUID))).build(); + } + + /** + * Creates new Ports */ + + @POST + @Produces({ MediaType.APPLICATION_JSON }) + @Consumes({ MediaType.APPLICATION_JSON }) + //@TypeHint(OpenStackPorts.class) + @StatusCodes({ + @ResponseCode(code = 201, condition = "Created"), + @ResponseCode(code = 400, condition = "Bad Request"), + @ResponseCode(code = 401, condition = "Unauthorized"), + @ResponseCode(code = 403, condition = "Forbidden"), + @ResponseCode(code = 404, condition = "Not Found"), + @ResponseCode(code = 409, condition = "Conflict"), + @ResponseCode(code = 501, condition = "Not Implemented"), + @ResponseCode(code = 503, condition = "MAC generation failure") }) + public Response createPorts(final NeutronPortRequest input) { + INeutronPortCRUD portInterface = NeutronNBInterfaces.getIfNBPortCRUD("default",this); + if (portInterface == null) { + throw new ServiceUnavailableException("Port CRUD Interface " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + INeutronNetworkCRUD networkInterface = NeutronNBInterfaces.getIfNBNetworkCRUD("default", this); + if (networkInterface == null) { + throw new ServiceUnavailableException("Network CRUD Interface " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + INeutronSubnetCRUD subnetInterface = NeutronNBInterfaces.getIfNBSubnetCRUD("default", this); + if (subnetInterface == null) { + throw new ServiceUnavailableException("Subnet CRUD Interface " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + if (input.isSingleton()) { + NeutronPort singleton = input.getSingleton(); + + /* + * the port must be part of an existing network, must not already exist, + * have a valid MAC and the MAC not be in use + */ + if (singleton.getNetworkUUID() == null) + return Response.status(400).build(); + if (portInterface.portExists(singleton.getID())) + return Response.status(400).build(); + if (!networkInterface.networkExists(singleton.getNetworkUUID())) + return Response.status(404).build(); + if (singleton.getMacAddress() == null || + !singleton.getMacAddress().matches("^([0-9A-F]{2}[:-]){5}([0-9A-F]{2})$")) + return Response.status(400).build(); + if (portInterface.macInUse(singleton.getMacAddress())) + return Response.status(409).build(); + Object[] instances = ServiceHelper.getGlobalInstances(INeutronPortAware.class, this, null); + if (instances != null) { + for (Object instance : instances) { + INeutronPortAware service = (INeutronPortAware) instance; + int status = service.canCreatePort(singleton); + if (status < 200 || status > 299) + return Response.status(status).build(); + } + } + /* + * if fixed IPs are specified, each one has to have an existing subnet ID + * that is in the same scoping network as the port. In addition, if an IP + * address is specified it has to be a valid address for the subnet and not + * already in use + */ + List fixedIPs = singleton.getFixedIPs(); + if (fixedIPs != null && fixedIPs.size() > 0) { + Iterator fixedIPIterator = fixedIPs.iterator(); + while (fixedIPIterator.hasNext()) { + Neutron_IPs ip = fixedIPIterator.next(); + if (ip.getSubnetUUID() == null) + return Response.status(400).build(); + if (!subnetInterface.subnetExists(ip.getSubnetUUID())) + return Response.status(400).build(); + NeutronSubnet subnet = subnetInterface.getSubnet(ip.getSubnetUUID()); + if (!singleton.getNetworkUUID().equalsIgnoreCase(subnet.getNetworkUUID())) + return Response.status(400).build(); + if (ip.getIpAddress() != null) { + if (!subnet.isValidIP(ip.getIpAddress())) + return Response.status(400).build(); + if (subnet.isIPInUse(ip.getIpAddress())) + return Response.status(409).build(); + } + } + } + + // add the port to the cache + portInterface.addPort(singleton); + if (instances != null) { + for (Object instance : instances) { + INeutronPortAware service = (INeutronPortAware) instance; + service.neutronPortCreated(singleton); + } + } + } else { + List bulk = input.getBulk(); + Iterator i = bulk.iterator(); + HashMap testMap = new HashMap(); + Object[] instances = ServiceHelper.getGlobalInstances(INeutronSubnetAware.class, this, null); + while (i.hasNext()) { + NeutronPort test = i.next(); + + /* + * the port must be part of an existing network, must not already exist, + * have a valid MAC and the MAC not be in use. Further the bulk request + * can't already contain a new port with the same UUID + */ + if (portInterface.portExists(test.getID())) + return Response.status(400).build(); + if (testMap.containsKey(test.getID())) + return Response.status(400).build(); + for (NeutronPort check : testMap.values()) { + if (test.getMacAddress().equalsIgnoreCase(check.getMacAddress())) + return Response.status(409).build(); + for (Neutron_IPs test_fixedIP : test.getFixedIPs()) { + for (Neutron_IPs check_fixedIP : check.getFixedIPs()) { + if (test_fixedIP.getIpAddress().equals(check_fixedIP.getIpAddress())) + return Response.status(409).build(); + } + } + } + testMap.put(test.getID(), test); + if (!networkInterface.networkExists(test.getNetworkUUID())) + return Response.status(404).build(); + if (!test.getMacAddress().matches("^([0-9A-F]{2}[:-]){5}([0-9A-F]{2})$")) + return Response.status(400).build(); + if (portInterface.macInUse(test.getMacAddress())) + return Response.status(409).build(); + if (instances != null) { + for (Object instance : instances) { + INeutronPortAware service = (INeutronPortAware) instance; + int status = service.canCreatePort(test); + if (status < 200 || status > 299) + return Response.status(status).build(); + } + } + /* + * if fixed IPs are specified, each one has to have an existing subnet ID + * that is in the same scoping network as the port. In addition, if an IP + * address is specified it has to be a valid address for the subnet and not + * already in use (or be the gateway IP address of the subnet) + */ + List fixedIPs = test.getFixedIPs(); + if (fixedIPs != null && fixedIPs.size() > 0) { + Iterator fixedIPIterator = fixedIPs.iterator(); + while (fixedIPIterator.hasNext()) { + Neutron_IPs ip = fixedIPIterator.next(); + if (ip.getSubnetUUID() == null) + return Response.status(400).build(); + if (!subnetInterface.subnetExists(ip.getSubnetUUID())) + return Response.status(400).build(); + NeutronSubnet subnet = subnetInterface.getSubnet(ip.getSubnetUUID()); + if (!test.getNetworkUUID().equalsIgnoreCase(subnet.getNetworkUUID())) + return Response.status(400).build(); + if (ip.getIpAddress() != null) { + if (!subnet.isValidIP(ip.getIpAddress())) + return Response.status(400).build(); + //TODO: need to add consideration for a fixed IP being assigned the same address as a allocated IP in the + //same bulk create + if (subnet.isIPInUse(ip.getIpAddress())) + return Response.status(409).build(); + } + } + } + } + + //once everything has passed, then we can add to the cache + i = bulk.iterator(); + while (i.hasNext()) { + NeutronPort test = i.next(); + portInterface.addPort(test); + if (instances != null) { + for (Object instance : instances) { + INeutronPortAware service = (INeutronPortAware) instance; + service.neutronPortCreated(test); + } + } + } + } + return Response.status(201).entity(input).build(); + } + + /** + * Updates a Port */ + + @Path("{portUUID}") + @PUT + @Produces({ MediaType.APPLICATION_JSON }) + @Consumes({ MediaType.APPLICATION_JSON }) + //@TypeHint(OpenStackPorts.class) + @StatusCodes({ + @ResponseCode(code = 200, condition = "Operation successful"), + @ResponseCode(code = 400, condition = "Bad Request"), + @ResponseCode(code = 401, condition = "Unauthorized"), + @ResponseCode(code = 403, condition = "Forbidden"), + @ResponseCode(code = 404, condition = "Not Found"), + @ResponseCode(code = 409, condition = "Conflict"), + @ResponseCode(code = 501, condition = "Not Implemented") }) + public Response updatePort( + @PathParam("portUUID") String portUUID, + NeutronPortRequest input + ) { + INeutronPortCRUD portInterface = NeutronNBInterfaces.getIfNBPortCRUD("default",this); + if (portInterface == null) { + throw new ServiceUnavailableException("Port CRUD Interface " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + INeutronSubnetCRUD subnetInterface = NeutronNBInterfaces.getIfNBSubnetCRUD("default", this); + if (subnetInterface == null) { + throw new ServiceUnavailableException("Subnet CRUD Interface " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + + // port has to exist and only a single delta is supported + if (!portInterface.portExists(portUUID)) + return Response.status(404).build(); + NeutronPort target = portInterface.getPort(portUUID); + if (!input.isSingleton()) + return Response.status(400).build(); + NeutronPort singleton = input.getSingleton(); + NeutronPort original = portInterface.getPort(portUUID); + + // deltas restricted by Neutron + if (singleton.getID() != null || singleton.getTenantID() != null || + singleton.getStatus() != null) + return Response.status(400).build(); + + Object[] instances = ServiceHelper.getGlobalInstances(INeutronPortAware.class, this, null); + if (instances != null) { + for (Object instance : instances) { + INeutronPortAware service = (INeutronPortAware) instance; + int status = service.canUpdatePort(singleton, original); + if (status < 200 || status > 299) + return Response.status(status).build(); + } + } + + // Verify the new fixed ips are valid + List fixedIPs = singleton.getFixedIPs(); + if (fixedIPs != null && fixedIPs.size() > 0) { + Iterator fixedIPIterator = fixedIPs.iterator(); + while (fixedIPIterator.hasNext()) { + Neutron_IPs ip = fixedIPIterator.next(); + if (ip.getSubnetUUID() == null) + return Response.status(400).build(); + if (!subnetInterface.subnetExists(ip.getSubnetUUID())) + return Response.status(400).build(); + NeutronSubnet subnet = subnetInterface.getSubnet(ip.getSubnetUUID()); + if (!target.getNetworkUUID().equalsIgnoreCase(subnet.getNetworkUUID())) + return Response.status(400).build(); + if (ip.getIpAddress() != null) { + if (!subnet.isValidIP(ip.getIpAddress())) + return Response.status(400).build(); + if (subnet.isIPInUse(ip.getIpAddress())) + return Response.status(409).build(); + } + } + } + +// TODO: Support change of security groups + // update the port and return the modified object + portInterface.updatePort(portUUID, singleton); + NeutronPort updatedPort = portInterface.getPort(portUUID); + if (instances != null) { + for (Object instance : instances) { + INeutronPortAware service = (INeutronPortAware) instance; + service.neutronPortUpdated(updatedPort); + } + } + return Response.status(200).entity( + new NeutronPortRequest(updatedPort)).build(); + + } + + /** + * Deletes a Port */ + + @Path("{portUUID}") + @DELETE + @StatusCodes({ + @ResponseCode(code = 204, condition = "No Content"), + @ResponseCode(code = 401, condition = "Unauthorized"), + @ResponseCode(code = 403, condition = "Forbidden"), + @ResponseCode(code = 404, condition = "Not Found"), + @ResponseCode(code = 501, condition = "Not Implemented") }) + public Response deletePort( + @PathParam("portUUID") String portUUID) { + INeutronPortCRUD portInterface = NeutronNBInterfaces.getIfNBPortCRUD("default",this); + if (portInterface == null) { + throw new ServiceUnavailableException("Port CRUD Interface " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + + // port has to exist and not be owned by anyone. then it can be removed from the cache + if (!portInterface.portExists(portUUID)) + return Response.status(404).build(); + NeutronPort port = portInterface.getPort(portUUID); + if (port.getDeviceID() != null || + port.getDeviceOwner() != null) + Response.status(403).build(); + NeutronPort singleton = portInterface.getPort(portUUID); + Object[] instances = ServiceHelper.getGlobalInstances(INeutronPortAware.class, this, null); + if (instances != null) { + for (Object instance : instances) { + INeutronPortAware service = (INeutronPortAware) instance; + int status = service.canDeletePort(singleton); + if (status < 200 || status > 299) + return Response.status(status).build(); + } + } + portInterface.removePort(portUUID); + if (instances != null) { + for (Object instance : instances) { + INeutronPortAware service = (INeutronPortAware) instance; + service.neutronPortDeleted(singleton); + } + } + return Response.status(204).build(); + } +} diff --git a/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronRouterRequest.java b/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronRouterRequest.java new file mode 100644 index 0000000000..1fcc9a9e91 --- /dev/null +++ b/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronRouterRequest.java @@ -0,0 +1,57 @@ +/* + * Copyright IBM Corporation, 2013. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.networkconfig.neutron.northbound; + +import java.util.List; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +import org.opendaylight.controller.networkconfig.neutron.NeutronRouter; + + +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) + +public class NeutronRouterRequest { + // See OpenStack Network API v2.0 Reference for description of + // annotated attributes + + @XmlElement(name="router") + NeutronRouter singletonRouter; + + @XmlElement(name="routers") + List bulkRequest; + + NeutronRouterRequest() { + } + + NeutronRouterRequest(List bulk) { + bulkRequest = bulk; + singletonRouter = null; + } + + NeutronRouterRequest(NeutronRouter router) { + singletonRouter = router; + } + + public List getBulk() { + return bulkRequest; + } + + public NeutronRouter getSingleton() { + return singletonRouter; + } + + public boolean isSingleton() { + return (singletonRouter != null); + } +} diff --git a/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronRoutersNorthbound.java b/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronRoutersNorthbound.java new file mode 100644 index 0000000000..0ffb085488 --- /dev/null +++ b/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronRoutersNorthbound.java @@ -0,0 +1,552 @@ +/* + * Copyright IBM Corporation, 2013. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.networkconfig.neutron.northbound; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import org.codehaus.enunciate.jaxrs.ResponseCode; +import org.codehaus.enunciate.jaxrs.StatusCodes; +import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD; +import org.opendaylight.controller.networkconfig.neutron.INeutronPortAware; +import org.opendaylight.controller.networkconfig.neutron.INeutronPortCRUD; +import org.opendaylight.controller.networkconfig.neutron.INeutronRouterAware; +import org.opendaylight.controller.networkconfig.neutron.INeutronRouterCRUD; +import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD; +import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork; +import org.opendaylight.controller.networkconfig.neutron.NeutronPort; +import org.opendaylight.controller.networkconfig.neutron.NeutronRouter; +import org.opendaylight.controller.networkconfig.neutron.NeutronRouter_Interface; +import org.opendaylight.controller.networkconfig.neutron.NeutronSubnet; +import org.opendaylight.controller.networkconfig.neutron.Neutron_IPs; +import org.opendaylight.controller.northbound.commons.RestMessages; +import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException; +import org.opendaylight.controller.sal.utils.ServiceHelper; + + +/** + * Open DOVE Northbound REST APIs.
+ * This class provides REST APIs for managing the open DOVE + * + *
+ *
+ * Authentication scheme : HTTP Basic
+ * Authentication realm : opendaylight
+ * Transport : HTTP and HTTPS
+ *
+ * HTTPS Authentication is disabled by default. Administrator can enable it in + * tomcat-server.xml after adding a proper keystore / SSL certificate from a + * trusted authority.
+ * More info : + * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration + * + */ + +@Path("/routers") +public class NeutronRoutersNorthbound { + + private NeutronRouter extractFields(NeutronRouter o, List fields) { + return o.extractFields(fields); + } + + /** + * Returns a list of all Routers */ + + @GET + @Produces({ MediaType.APPLICATION_JSON }) + //@TypeHint(OpenStackRouters.class) + @StatusCodes({ + @ResponseCode(code = 200, condition = "Operation successful"), + @ResponseCode(code = 401, condition = "Unauthorized"), + @ResponseCode(code = 501, condition = "Not Implemented") }) + public Response listRouters( + // return fields + @QueryParam("fields") List fields, + // note: openstack isn't clear about filtering on lists, so we aren't handling them + @QueryParam("id") String queryID, + @QueryParam("name") String queryName, + @QueryParam("admin_state_up") String queryAdminStateUp, + @QueryParam("status") String queryStatus, + @QueryParam("tenant_id") String queryTenantID, + @QueryParam("external_gateway_info") String queryExternalGatewayInfo, + // pagination + @QueryParam("limit") String limit, + @QueryParam("marker") String marker, + @QueryParam("page_reverse") String pageReverse + // sorting not supported + ) { + INeutronRouterCRUD routerInterface = NeutronNBInterfaces.getIfNBRouterCRUD("default",this); + if (routerInterface == null) { + throw new ServiceUnavailableException("Router CRUD Interface " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + List allRouters = routerInterface.getAllRouters(); + List ans = new ArrayList(); + Iterator i = allRouters.iterator(); + while (i.hasNext()) { + NeutronRouter oSS = i.next(); + if ((queryID == null || queryID.equals(oSS.getID())) && + (queryName == null || queryName.equals(oSS.getName())) && + (queryAdminStateUp == null || queryAdminStateUp.equals(oSS.getAdminStateUp())) && + (queryStatus == null || queryStatus.equals(oSS.getStatus())) && + (queryExternalGatewayInfo == null || queryExternalGatewayInfo.equals(oSS.getExternalGatewayInfo())) && + (queryTenantID == null || queryTenantID.equals(oSS.getTenantID()))) { + if (fields.size() > 0) + ans.add(extractFields(oSS,fields)); + else + ans.add(oSS); + } + } + //TODO: apply pagination to results + return Response.status(200).entity( + new NeutronRouterRequest(ans)).build(); + } + + /** + * Returns a specific Router */ + + @Path("{routerUUID}") + @GET + @Produces({ MediaType.APPLICATION_JSON }) + //@TypeHint(OpenStackRouters.class) + @StatusCodes({ + @ResponseCode(code = 200, condition = "Operation successful"), + @ResponseCode(code = 401, condition = "Unauthorized"), + @ResponseCode(code = 403, condition = "Forbidden"), + @ResponseCode(code = 404, condition = "Not Found"), + @ResponseCode(code = 501, condition = "Not Implemented") }) + public Response showRouter( + @PathParam("routerUUID") String routerUUID, + // return fields + @QueryParam("fields") List fields) { + INeutronRouterCRUD routerInterface = NeutronNBInterfaces.getIfNBRouterCRUD("default",this); + if (routerInterface == null) { + throw new ServiceUnavailableException("Router CRUD Interface " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + if (!routerInterface.routerExists(routerUUID)) + return Response.status(404).build(); + if (fields.size() > 0) { + NeutronRouter ans = routerInterface.getRouter(routerUUID); + return Response.status(200).entity( + new NeutronRouterRequest(extractFields(ans, fields))).build(); + } else + return Response.status(200).entity( + new NeutronRouterRequest(routerInterface.getRouter(routerUUID))).build(); + } + + /** + * Creates new Routers */ + + @POST + @Produces({ MediaType.APPLICATION_JSON }) + @Consumes({ MediaType.APPLICATION_JSON }) + //@TypeHint(OpenStackRouters.class) + @StatusCodes({ + @ResponseCode(code = 201, condition = "Created"), + @ResponseCode(code = 400, condition = "Bad Request"), + @ResponseCode(code = 401, condition = "Unauthorized"), + @ResponseCode(code = 501, condition = "Not Implemented") }) + public Response createRouters(final NeutronRouterRequest input) { + INeutronRouterCRUD routerInterface = NeutronNBInterfaces.getIfNBRouterCRUD("default",this); + if (routerInterface == null) { + throw new ServiceUnavailableException("Router CRUD Interface " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + INeutronNetworkCRUD networkInterface = NeutronNBInterfaces.getIfNBNetworkCRUD("default", this); + if (networkInterface == null) { + throw new ServiceUnavailableException("Network CRUD Interface " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + if (input.isSingleton()) { + NeutronRouter singleton = input.getSingleton(); + + /* + * verify that the router doesn't already exist (issue: is deeper inspection necessary?) + * if there is external gateway information provided, verify that the specified network + * exists and has been designated as "router:external" + */ + if (routerInterface.routerExists(singleton.getID())) + return Response.status(400).build(); + if (singleton.getExternalGatewayInfo() != null) { + String externNetworkPtr = singleton.getExternalGatewayInfo().getNetworkID(); + if (!networkInterface.networkExists(externNetworkPtr)) + return Response.status(400).build(); + NeutronNetwork externNetwork = networkInterface.getNetwork(externNetworkPtr); + if (!externNetwork.isRouterExternal()) + return Response.status(400).build(); + } + Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null); + if (instances != null) { + for (Object instance : instances) { + INeutronRouterAware service = (INeutronRouterAware) instance; + int status = service.canCreateRouter(singleton); + if (status < 200 || status > 299) + return Response.status(status).build(); + } + } + + /* + * add router to the cache + */ + routerInterface.addRouter(singleton); + if (instances != null) { + for (Object instance : instances) { + INeutronRouterAware service = (INeutronRouterAware) instance; + service.neutronRouterCreated(singleton); + } + } + } else { + + /* + * only singleton router creates supported + */ + return Response.status(400).build(); + } + return Response.status(201).entity(input).build(); + } + + /** + * Updates a Router */ + + @Path("{routerUUID}") + @PUT + @Produces({ MediaType.APPLICATION_JSON }) + @Consumes({ MediaType.APPLICATION_JSON }) + //@TypeHint(OpenStackRouters.class) + @StatusCodes({ + @ResponseCode(code = 200, condition = "Operation successful"), + @ResponseCode(code = 400, condition = "Bad Request"), + @ResponseCode(code = 401, condition = "Unauthorized"), + @ResponseCode(code = 404, condition = "Not Found"), + @ResponseCode(code = 501, condition = "Not Implemented") }) + public Response updateRouter( + @PathParam("routerUUID") String routerUUID, + NeutronRouterRequest input + ) { + INeutronRouterCRUD routerInterface = NeutronNBInterfaces.getIfNBRouterCRUD("default",this); + if (routerInterface == null) { + throw new ServiceUnavailableException("Router CRUD Interface " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + INeutronNetworkCRUD networkInterface = NeutronNBInterfaces.getIfNBNetworkCRUD("default", this); + if (networkInterface == null) { + throw new ServiceUnavailableException("Network CRUD Interface " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + + /* + * router has to exist and only a single delta can be supplied + */ + if (!routerInterface.routerExists(routerUUID)) + return Response.status(404).build(); + if (!input.isSingleton()) + return Response.status(400).build(); + NeutronRouter singleton = input.getSingleton(); + NeutronRouter original = routerInterface.getRouter(routerUUID); + + /* + * attribute changes blocked by Neutron + */ + if (singleton.getID() != null || singleton.getTenantID() != null || + singleton.getStatus() != null) + return Response.status(400).build(); + + Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null); + if (instances != null) { + for (Object instance : instances) { + INeutronRouterAware service = (INeutronRouterAware) instance; + int status = service.canUpdateRouter(singleton, original); + if (status < 200 || status > 299) + return Response.status(status).build(); + } + } + /* + * if the external gateway info is being changed, verify that the new network + * exists and has been designated as an external network + */ + if (singleton.getExternalGatewayInfo() != null) { + String externNetworkPtr = singleton.getExternalGatewayInfo().getNetworkID(); + if (!networkInterface.networkExists(externNetworkPtr)) + return Response.status(400).build(); + NeutronNetwork externNetwork = networkInterface.getNetwork(externNetworkPtr); + if (!externNetwork.isRouterExternal()) + return Response.status(400).build(); + } + + /* + * update the router entry and return the modified object + */ + routerInterface.updateRouter(routerUUID, singleton); + NeutronRouter updatedRouter = routerInterface.getRouter(routerUUID); + if (instances != null) { + for (Object instance : instances) { + INeutronRouterAware service = (INeutronRouterAware) instance; + service.neutronRouterUpdated(updatedRouter); + } + } + return Response.status(200).entity( + new NeutronRouterRequest(routerInterface.getRouter(routerUUID))).build(); + + } + + /** + * Deletes a Router */ + + @Path("{routerUUID}") + @DELETE + @StatusCodes({ + @ResponseCode(code = 204, condition = "No Content"), + @ResponseCode(code = 401, condition = "Unauthorized"), + @ResponseCode(code = 404, condition = "Not Found"), + @ResponseCode(code = 409, condition = "Conflict"), + @ResponseCode(code = 501, condition = "Not Implemented") }) + public Response deleteRouter( + @PathParam("routerUUID") String routerUUID) { + INeutronRouterCRUD routerInterface = NeutronNBInterfaces.getIfNBRouterCRUD("default",this); + if (routerInterface == null) { + throw new ServiceUnavailableException("Router CRUD Interface " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + + /* + * verify that the router exists and is not in use before removing it + */ + if (!routerInterface.routerExists(routerUUID)) + return Response.status(404).build(); + if (routerInterface.routerInUse(routerUUID)) + return Response.status(409).build(); + NeutronRouter singleton = routerInterface.getRouter(routerUUID); + Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null); + if (instances != null) { + for (Object instance : instances) { + INeutronRouterAware service = (INeutronRouterAware) instance; + int status = service.canDeleteRouter(singleton); + if (status < 200 || status > 299) + return Response.status(status).build(); + } + } + routerInterface.removeRouter(routerUUID); + if (instances != null) { + for (Object instance : instances) { + INeutronRouterAware service = (INeutronRouterAware) instance; + service.neutronRouterDeleted(singleton); + } + } + return Response.status(204).build(); + } + + /** + * Adds an interface to a router */ + + @Path("{routerUUID}/add_router_interface") + @PUT + @Produces({ MediaType.APPLICATION_JSON }) + @Consumes({ MediaType.APPLICATION_JSON }) + //@TypeHint(OpenStackRouterInterfaces.class) + @StatusCodes({ + @ResponseCode(code = 200, condition = "Operation successful"), + @ResponseCode(code = 400, condition = "Bad Request"), + @ResponseCode(code = 401, condition = "Unauthorized"), + @ResponseCode(code = 404, condition = "Not Found"), + @ResponseCode(code = 409, condition = "Conflict"), + @ResponseCode(code = 501, condition = "Not Implemented") }) + public Response addRouterInterface( + @PathParam("routerUUID") String routerUUID, + NeutronRouter_Interface input + ) { + INeutronRouterCRUD routerInterface = NeutronNBInterfaces.getIfNBRouterCRUD("default",this); + if (routerInterface == null) { + throw new ServiceUnavailableException("Router CRUD Interface " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + INeutronPortCRUD portInterface = NeutronNBInterfaces.getIfNBPortCRUD("default",this); + if (portInterface == null) { + throw new ServiceUnavailableException("Port CRUD Interface " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + INeutronSubnetCRUD subnetInterface = NeutronNBInterfaces.getIfNBSubnetCRUD("default",this); + if (subnetInterface == null) { + throw new ServiceUnavailableException("Subnet CRUD Interface " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + + /* + * While the Neutron specification says that the router has to exist and the input can only specify either a subnet id + * or a port id, but not both, this code assumes that the plugin has filled everything in for us and so both must be present + */ + if (!routerInterface.routerExists(routerUUID)) + return Response.status(400).build(); + NeutronRouter target = routerInterface.getRouter(routerUUID); + if (input.getSubnetUUID() == null || + input.getPortUUID() == null) + return Response.status(400).build(); + + // check that the port is part of the subnet + NeutronSubnet targetSubnet = subnetInterface.getSubnet(input.getSubnetUUID()); + if (targetSubnet == null) + return Response.status(400).build(); + NeutronPort targetPort = portInterface.getPort(input.getPortUUID()); + if (targetPort == null) + return Response.status(400).build(); + if (!targetSubnet.getPortsInSubnet().contains(targetPort)) + return Response.status(400).build(); + + if (targetPort.getFixedIPs().size() != 1) + return Response.status(400).build(); + if (targetPort.getDeviceID() != null || + targetPort.getDeviceOwner() != null) + return Response.status(409).build(); + + //mark the port device id and device owner fields + targetPort.setDeviceOwner("network:router_interface"); + targetPort.setDeviceID(routerUUID); + + target.addInterface(input.getPortUUID(), input); + Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null); + if (instances != null) { + for (Object instance : instances) { + INeutronRouterAware service = (INeutronRouterAware) instance; + service.neutronRouterInterfaceAttached(target, input); + } + } + + return Response.status(200).entity(input).build(); + } + + /** + * Removes an interface to a router */ + + @Path("{routerUUID}/remove_router_interface") + @PUT + @Produces({ MediaType.APPLICATION_JSON }) + @Consumes({ MediaType.APPLICATION_JSON }) + //@TypeHint(OpenStackRouterInterfaces.class) + @StatusCodes({ + @ResponseCode(code = 200, condition = "Operation successful"), + @ResponseCode(code = 400, condition = "Bad Request"), + @ResponseCode(code = 401, condition = "Unauthorized"), + @ResponseCode(code = 404, condition = "Not Found"), + @ResponseCode(code = 409, condition = "Conflict"), + @ResponseCode(code = 501, condition = "Not Implemented") }) + public Response removeRouterInterface( + @PathParam("routerUUID") String routerUUID, + NeutronRouter_Interface input + ) { + INeutronRouterCRUD routerInterface = NeutronNBInterfaces.getIfNBRouterCRUD("default",this); + if (routerInterface == null) { + throw new ServiceUnavailableException("Router CRUD Interface " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + INeutronPortCRUD portInterface = NeutronNBInterfaces.getIfNBPortCRUD("default",this); + if (portInterface == null) { + throw new ServiceUnavailableException("Port CRUD Interface " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + INeutronSubnetCRUD subnetInterface = NeutronNBInterfaces.getIfNBSubnetCRUD("default",this); + if (subnetInterface == null) { + throw new ServiceUnavailableException("Subnet CRUD Interface " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + + // verify the router exists + if (!routerInterface.routerExists(routerUUID)) + return Response.status(400).build(); + NeutronRouter target = routerInterface.getRouter(routerUUID); + + /* + * remove by subnet id. Collect information about the impacted router for the response and + * remove the port corresponding to the gateway IP address of the subnet + */ + if (input.getPortUUID() == null && + input.getSubnetUUID() != null) { + NeutronPort port = portInterface.getGatewayPort(input.getSubnetUUID()); + if (port == null) + return Response.status(404).build(); + input.setPortUUID(port.getID()); + input.setID(target.getID()); + input.setTenantID(target.getTenantID()); + + // reset the port ownership + port.setDeviceID(null); + port.setDeviceOwner(null); + + target.removeInterface(input.getPortUUID()); + Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null); + if (instances != null) { + for (Object instance : instances) { + INeutronRouterAware service = (INeutronRouterAware) instance; + service.neutronRouterInterfaceDetached(target, input); + } + } + return Response.status(200).entity(input).build(); + } + + /* + * remove by port id. collect information about the impacted router for the response + * remove the interface and reset the port ownership + */ + if (input.getPortUUID() != null && + input.getSubnetUUID() == null) { + NeutronRouter_Interface targetInterface = target.getInterfaces().get(input.getPortUUID()); + input.setSubnetUUID(targetInterface.getSubnetUUID()); + input.setID(target.getID()); + input.setTenantID(target.getTenantID()); + NeutronPort port = portInterface.getPort(input.getPortUUID()); + port.setDeviceID(null); + port.setDeviceOwner(null); + target.removeInterface(input.getPortUUID()); + Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null); + for (Object instance : instances) { + INeutronRouterAware service = (INeutronRouterAware) instance; + service.neutronRouterInterfaceDetached(target, input); + } + return Response.status(200).entity(input).build(); + } + + /* + * remove by both port and subnet ID. Verify that the first fixed IP of the port is a valid + * IP address for the subnet, and then remove the interface, collecting information about the + * impacted router for the response and reset port ownership + */ + if (input.getPortUUID() != null && + input.getSubnetUUID() != null) { + NeutronPort port = portInterface.getPort(input.getPortUUID()); + NeutronSubnet subnet = subnetInterface.getSubnet(input.getSubnetUUID()); + if (!subnet.isValidIP(port.getFixedIPs().get(0).getIpAddress())) + return Response.status(409).build(); + input.setID(target.getID()); + input.setTenantID(target.getTenantID()); + port.setDeviceID(null); + port.setDeviceOwner(null); + target.removeInterface(input.getPortUUID()); + Object[] instances = ServiceHelper.getGlobalInstances(INeutronRouterAware.class, this, null); + for (Object instance : instances) { + INeutronRouterAware service = (INeutronRouterAware) instance; + service.neutronRouterInterfaceDetached(target, input); + } + return Response.status(200).entity(input).build(); + } + + // have to specify either a port ID or a subnet ID + return Response.status(400).build(); + } +} diff --git a/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronSubnetRequest.java b/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronSubnetRequest.java new file mode 100644 index 0000000000..ab91399879 --- /dev/null +++ b/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronSubnetRequest.java @@ -0,0 +1,56 @@ +/* + * Copyright IBM Corporation, 2013. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.networkconfig.neutron.northbound; + +import java.util.List; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +import org.opendaylight.controller.networkconfig.neutron.NeutronSubnet; + +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) + +public class NeutronSubnetRequest { + // See OpenStack Network API v2.0 Reference for description of + // annotated attributes + + @XmlElement(name="subnet") + NeutronSubnet singletonSubnet; + + @XmlElement(name="subnets") + List bulkRequest; + + NeutronSubnetRequest() { + } + + NeutronSubnetRequest(List bulk) { + bulkRequest = bulk; + singletonSubnet = null; + } + + NeutronSubnetRequest(NeutronSubnet subnet) { + singletonSubnet = subnet; + } + + public NeutronSubnet getSingleton() { + return singletonSubnet; + } + + public List getBulk() { + return bulkRequest; + } + + public boolean isSingleton() { + return (singletonSubnet != null); + } +} diff --git a/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronSubnetsNorthbound.java b/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronSubnetsNorthbound.java new file mode 100644 index 0000000000..1aaee93cea --- /dev/null +++ b/opendaylight/northbound/networkconfiguration/neutron/src/main/java/org/opendaylight/controller/networkconfig/neutron/northbound/NeutronSubnetsNorthbound.java @@ -0,0 +1,385 @@ +/* + * Copyright IBM Corporation, 2013. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.controller.networkconfig.neutron.northbound; + + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import org.codehaus.enunciate.jaxrs.ResponseCode; +import org.codehaus.enunciate.jaxrs.StatusCodes; +import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkAware; +import org.opendaylight.controller.networkconfig.neutron.INeutronNetworkCRUD; +import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetAware; +import org.opendaylight.controller.networkconfig.neutron.INeutronSubnetCRUD; +import org.opendaylight.controller.networkconfig.neutron.NeutronNetwork; +import org.opendaylight.controller.networkconfig.neutron.NeutronSubnet; +import org.opendaylight.controller.northbound.commons.RestMessages; +import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException; +import org.opendaylight.controller.sal.utils.ServiceHelper; + +/** + * Open DOVE Northbound REST APIs.
+ * This class provides REST APIs for managing open DOVE internals related to Subnets + * + *
+ *
+ * Authentication scheme : HTTP Basic
+ * Authentication realm : opendaylight
+ * Transport : HTTP and HTTPS
+ *
+ * HTTPS Authentication is disabled by default. Administrator can enable it in + * tomcat-server.xml after adding a proper keystore / SSL certificate from a + * trusted authority.
+ * More info : + * http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html#Configuration + * + */ + +@Path("/subnets") +public class NeutronSubnetsNorthbound { + + private NeutronSubnet extractFields(NeutronSubnet o, List fields) { + return o.extractFields(fields); + } + + + /** + * Returns a list of all Subnets */ + @GET + @Produces({ MediaType.APPLICATION_JSON }) + //@TypeHint(OpenStackSubnets.class) + @StatusCodes({ + @ResponseCode(code = 200, condition = "Operation successful"), + @ResponseCode(code = 401, condition = "Unauthorized"), + @ResponseCode(code = 501, condition = "Not Implemented") }) + public Response listSubnets( + // return fields + @QueryParam("fields") List fields, + // note: openstack isn't clear about filtering on lists, so we aren't handling them + @QueryParam("id") String queryID, + @QueryParam("network_id") String queryNetworkID, + @QueryParam("name") String queryName, + @QueryParam("ip_version") String queryIPVersion, + @QueryParam("cidr") String queryCIDR, + @QueryParam("gateway_ip") String queryGatewayIP, + @QueryParam("enable_dhcp") String queryEnableDHCP, + @QueryParam("tenant_id") String queryTenantID, + // pagination + @QueryParam("limit") String limit, + @QueryParam("marker") String marker, + @QueryParam("page_reverse") String pageReverse + // sorting not supported + ) { + INeutronSubnetCRUD subnetInterface = NeutronNBInterfaces.getIfNBSubnetCRUD("default", this); + if (subnetInterface == null) { + throw new ServiceUnavailableException("Subnet CRUD Interface " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + List allNetworks = subnetInterface.getAllSubnets(); + List ans = new ArrayList(); + Iterator i = allNetworks.iterator(); + while (i.hasNext()) { + NeutronSubnet oSS = i.next(); + if ((queryID == null || queryID.equals(oSS.getID())) && + (queryNetworkID == null || queryNetworkID.equals(oSS.getNetworkUUID())) && + (queryName == null || queryName.equals(oSS.getName())) && + (queryIPVersion == null || queryIPVersion.equals(oSS.getIpVersion())) && + (queryCIDR == null || queryCIDR.equals(oSS.getCidr())) && + (queryGatewayIP == null || queryGatewayIP.equals(oSS.getGatewayIP())) && + (queryEnableDHCP == null || queryEnableDHCP.equals(oSS.getEnableDHCP())) && + (queryTenantID == null || queryTenantID.equals(oSS.getTenantID()))) { + if (fields.size() > 0) + ans.add(extractFields(oSS,fields)); + else + ans.add(oSS); + } + } + //TODO: apply pagination to results + return Response.status(200).entity( + new NeutronSubnetRequest(ans)).build(); + } + + /** + * Returns a specific Subnet */ + + @Path("{subnetUUID}") + @GET + @Produces({ MediaType.APPLICATION_JSON }) + //@TypeHint(OpenStackSubnets.class) + @StatusCodes({ + @ResponseCode(code = 200, condition = "Operation successful"), + @ResponseCode(code = 401, condition = "Unauthorized"), + @ResponseCode(code = 404, condition = "Not Found"), + @ResponseCode(code = 501, condition = "Not Implemented") }) + public Response showSubnet( + @PathParam("subnetUUID") String subnetUUID, + // return fields + @QueryParam("fields") List fields) { + INeutronSubnetCRUD subnetInterface = NeutronNBInterfaces.getIfNBSubnetCRUD("default",this); + if (subnetInterface == null) { + throw new ServiceUnavailableException("Subnet CRUD Interface " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + if (!subnetInterface.subnetExists(subnetUUID)) + return Response.status(404).build(); + if (fields.size() > 0) { + NeutronSubnet ans = subnetInterface.getSubnet(subnetUUID); + return Response.status(200).entity( + new NeutronSubnetRequest(extractFields(ans, fields))).build(); + } else + return Response.status(200).entity( + new NeutronSubnetRequest(subnetInterface.getSubnet(subnetUUID))).build(); + } + + /** + * Creates new Subnets */ + + @POST + @Produces({ MediaType.APPLICATION_JSON }) + @Consumes({ MediaType.APPLICATION_JSON }) + //@TypeHint(OpenStackSubnets.class) + @StatusCodes({ + @ResponseCode(code = 201, condition = "Created"), + @ResponseCode(code = 400, condition = "Bad Request"), + @ResponseCode(code = 401, condition = "Unauthorized"), + @ResponseCode(code = 403, condition = "Forbidden"), + @ResponseCode(code = 404, condition = "Not Found"), + @ResponseCode(code = 409, condition = "Conflict"), + @ResponseCode(code = 501, condition = "Not Implemented") }) + public Response createSubnets(final NeutronSubnetRequest input) { + INeutronSubnetCRUD subnetInterface = NeutronNBInterfaces.getIfNBSubnetCRUD("default",this); + if (subnetInterface == null) { + throw new ServiceUnavailableException("Subnet CRUD Interface " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + INeutronNetworkCRUD networkInterface = NeutronNBInterfaces.getIfNBNetworkCRUD("default", this); + if (networkInterface == null) { + throw new ServiceUnavailableException("Network CRUD Interface " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + if (input.isSingleton()) { + NeutronSubnet singleton = input.getSingleton(); + + /* + * Verify that the subnet doesn't already exist (Issue: is a deeper check necessary?) + * the specified network exists, the subnet has a valid network address, + * and that the gateway IP doesn't overlap with the allocation pools + * *then* add the subnet to the cache + */ + if (subnetInterface.subnetExists(singleton.getID())) + return Response.status(400).build(); + if (!networkInterface.networkExists(singleton.getNetworkUUID())) + return Response.status(404).build(); + if (!singleton.isValidCIDR()) + return Response.status(400).build(); + singleton.initDefaults(); + if (singleton.gatewayIP_Pool_overlap()) + return Response.status(409).build(); + Object[] instances = ServiceHelper.getGlobalInstances(INeutronSubnetAware.class, this, null); + if (instances != null) { + for (Object instance : instances) { + INeutronSubnetAware service = (INeutronSubnetAware) instance; + int status = service.canCreateSubnet(singleton); + if (status < 200 || status > 299) + return Response.status(status).build(); + } + } + subnetInterface.addSubnet(singleton); + if (instances != null) { + for (Object instance : instances) { + INeutronSubnetAware service = (INeutronSubnetAware) instance; + service.neutronSubnetCreated(singleton); + } + } + } else { + List bulk = input.getBulk(); + Iterator i = bulk.iterator(); + HashMap testMap = new HashMap(); + Object[] instances = ServiceHelper.getGlobalInstances(INeutronSubnetAware.class, this, null); + while (i.hasNext()) { + NeutronSubnet test = i.next(); + + /* + * Verify that the subnet doesn't already exist (Issue: is a deeper check necessary?) + * the specified network exists, the subnet has a valid network address, + * and that the gateway IP doesn't overlap with the allocation pools, + * and that the bulk request doesn't already contain a subnet with this id + */ + + test.initDefaults(); + if (subnetInterface.subnetExists(test.getID())) + return Response.status(400).build(); + if (testMap.containsKey(test.getID())) + return Response.status(400).build(); + testMap.put(test.getID(), test); + if (!networkInterface.networkExists(test.getNetworkUUID())) + return Response.status(404).build(); + if (!test.isValidCIDR()) + return Response.status(400).build(); + if (test.gatewayIP_Pool_overlap()) + return Response.status(409).build(); + if (instances != null) { + for (Object instance : instances) { + INeutronSubnetAware service = (INeutronSubnetAware) instance; + int status = service.canCreateSubnet(test); + if (status < 200 || status > 299) + return Response.status(status).build(); + } + } + } + + /* + * now, each element of the bulk request can be added to the cache + */ + i = bulk.iterator(); + while (i.hasNext()) { + NeutronSubnet test = i.next(); + subnetInterface.addSubnet(test); + if (instances != null) { + for (Object instance : instances) { + INeutronSubnetAware service = (INeutronSubnetAware) instance; + service.neutronSubnetCreated(test); + } + } + } + } + return Response.status(201).entity(input).build(); + } + + /** + * Updates a Subnet */ + + @Path("{subnetUUID}") + @PUT + @Produces({ MediaType.APPLICATION_JSON }) + @Consumes({ MediaType.APPLICATION_JSON }) + //@TypeHint(OpenStackSubnets.class) + @StatusCodes({ + @ResponseCode(code = 200, condition = "Operation successful"), + @ResponseCode(code = 400, condition = "Bad Request"), + @ResponseCode(code = 401, condition = "Unauthorized"), + @ResponseCode(code = 403, condition = "Forbidden"), + @ResponseCode(code = 404, condition = "Not Found"), + @ResponseCode(code = 501, condition = "Not Implemented") }) + public Response updateSubnet( + @PathParam("subnetUUID") String subnetUUID, final NeutronSubnetRequest input + ) { + INeutronSubnetCRUD subnetInterface = NeutronNBInterfaces.getIfNBSubnetCRUD("default", this); + if (subnetInterface == null) { + throw new ServiceUnavailableException("Subnet CRUD Interface " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + + /* + * verify the subnet exists and there is only one delta provided + */ + if (!subnetInterface.subnetExists(subnetUUID)) + return Response.status(404).build(); + if (!input.isSingleton()) + return Response.status(400).build(); + NeutronSubnet delta = input.getSingleton(); + NeutronSubnet original = subnetInterface.getSubnet(subnetUUID); + + /* + * updates restricted by Neutron + */ + if (delta.getID() != null || delta.getTenantID() != null || + delta.getIpVersion() != null || delta.getCidr() != null || + delta.getAllocationPools() != null) + return Response.status(400).build(); + + Object[] instances = ServiceHelper.getGlobalInstances(INeutronSubnetAware.class, this, null); + if (instances != null) { + for (Object instance : instances) { + INeutronSubnetAware service = (INeutronSubnetAware) instance; + int status = service.canUpdateSubnet(delta, original); + if (status < 200 || status > 299) + return Response.status(status).build(); + } + } + + /* + * update the object and return it + */ + subnetInterface.updateSubnet(subnetUUID, delta); + NeutronSubnet updatedSubnet = subnetInterface.getSubnet(subnetUUID); + if (instances != null) { + for (Object instance : instances) { + INeutronSubnetAware service = (INeutronSubnetAware) instance; + service.neutronSubnetUpdated(updatedSubnet); + } + } + return Response.status(200).entity( + new NeutronSubnetRequest(subnetInterface.getSubnet(subnetUUID))).build(); + } + + /** + * Deletes a Subnet */ + + @Path("{subnetUUID}") + @DELETE + @StatusCodes({ + @ResponseCode(code = 204, condition = "No Content"), + @ResponseCode(code = 401, condition = "Unauthorized"), + @ResponseCode(code = 404, condition = "Not Found"), + @ResponseCode(code = 409, condition = "Conflict"), + @ResponseCode(code = 501, condition = "Not Implemented") }) + public Response deleteSubnet( + @PathParam("subnetUUID") String subnetUUID) { + INeutronSubnetCRUD subnetInterface = NeutronNBInterfaces.getIfNBSubnetCRUD("default", this); + if (subnetInterface == null) { + throw new ServiceUnavailableException("Network CRUD Interface " + + RestMessages.SERVICEUNAVAILABLE.toString()); + } + + /* + * verify the subnet exists and it isn't currently in use + */ + if (!subnetInterface.subnetExists(subnetUUID)) + return Response.status(404).build(); + if (subnetInterface.subnetInUse(subnetUUID)) + return Response.status(409).build(); + NeutronSubnet singleton = subnetInterface.getSubnet(subnetUUID); + Object[] instances = ServiceHelper.getGlobalInstances(INeutronSubnetAware.class, this, null); + if (instances != null) { + for (Object instance : instances) { + INeutronSubnetAware service = (INeutronSubnetAware) instance; + int status = service.canDeleteSubnet(singleton); + if (status < 200 || status > 299) + return Response.status(status).build(); + } + } + + /* + * remove it and return 204 status + */ + subnetInterface.removeSubnet(subnetUUID); + if (instances != null) { + for (Object instance : instances) { + INeutronSubnetAware service = (INeutronSubnetAware) instance; + service.neutronSubnetDeleted(singleton); + } + } + return Response.status(204).build(); + } +} diff --git a/opendaylight/northbound/networkconfiguration/neutron/src/main/resources/WEB-INF/web.xml b/opendaylight/northbound/networkconfiguration/neutron/src/main/resources/WEB-INF/web.xml new file mode 100644 index 0000000000..dccd1332c9 --- /dev/null +++ b/opendaylight/northbound/networkconfiguration/neutron/src/main/resources/WEB-INF/web.xml @@ -0,0 +1,49 @@ + + + + JAXRSNeutron + com.sun.jersey.spi.container.servlet.ServletContainer + + javax.ws.rs.Application + org.opendaylight.controller.networkconfig.neutron.northbound.NeutronNorthboundRSApplication + + 1 + + + + JAXRSNeutron + /* + + + + NB api + /* + + + System-Admin + Network-Admin + Network-Operator + Container-User + + + + + System-Admin + + + Network-Admin + + + Network-Operator + + + Container-User + + + + BASIC + opendaylight + + diff --git a/opendaylight/northbound/networkconfiguration/neutron/src/main/resources/org/opendaylight/controller/networkconfig/neutron/northbound/jaxb.properties b/opendaylight/northbound/networkconfiguration/neutron/src/main/resources/org/opendaylight/controller/networkconfig/neutron/northbound/jaxb.properties new file mode 100644 index 0000000000..5837a4c258 --- /dev/null +++ b/opendaylight/northbound/networkconfiguration/neutron/src/main/resources/org/opendaylight/controller/networkconfig/neutron/northbound/jaxb.properties @@ -0,0 +1 @@ +javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory \ No newline at end of file -- 2.36.6