Fix to set/delete Switch Configuration using Northbound API 23/823/2
authorPramila Singh <pramisin@cisco.com>
Thu, 8 Aug 2013 20:59:25 +0000 (13:59 -0700)
committerPramila Singh <pramisin@cisco.com>
Thu, 8 Aug 2013 20:59:25 +0000 (13:59 -0700)
Change-Id: Ib3d7184a64bba4341637052ae96ae104073a64bc
Signed-off-by: Pramila Singh <pramisin@cisco.com>
opendaylight/containermanager/api/src/main/java/org/opendaylight/controller/containermanager/IContainerManager.java
opendaylight/northbound/integrationtest/src/test/java/org/opendaylight/controller/northbound/integrationtest/NorthboundIT.java
opendaylight/northbound/switchmanager/src/main/java/org/opendaylight/controller/switchmanager/northbound/SwitchNorthbound.java
opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Description.java
opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/ForwardingMode.java
opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Property.java
opendaylight/web/devices/src/main/java/org/opendaylight/controller/devices/web/Devices.java

index b956d76..89c0c0b 100644 (file)
@@ -21,9 +21,9 @@ import org.opendaylight.controller.sal.utils.Status;
 public interface IContainerManager {
 
     /**
-     * Returns a list of Containers that currently exist.
+     * Returns true if there are any non-default Containers present.
      *
-     * @return  array of String Container names
+     * @return  true, if any non-default container is present, else false
      */
     public boolean hasNonDefaultContainer();
 
index dff17ff..553505f 100644 (file)
@@ -486,39 +486,12 @@ public class NorthboundIT {
         testNodeConnectorProperties(nodeConnectorProperties, nodeConnectorId_3, ncType, nodeId_3, nodeType, ncState,
                 ncCapabilities, ncBandwidth);
 
-        // Test delete node property
-        // Delete timestamp property from node1
-        result = getJsonResult(baseURL + "node/STUB/" + nodeId_1 + "/property/timeStamp", "DELETE");
-        Assert.assertEquals(200, httpResponseCode.intValue());
-
-        // Check node1
-        result = getJsonResult(baseURL + "nodes");
-        jt = new JSONTokener(result);
-        json = new JSONObject(jt);
-        node = getJsonInstance(json, "nodeProperties", nodeId_1);
-        Assert.assertNotNull(node);
-        testNodeProperties(node, nodeId_1, nodeType, null, null, actionsValue_1, capabilitiesValue_1, tablesValue_1,
-                buffersValue_1);
-
-        // Delete actions property from node2
-        result = getJsonResult(baseURL + "node/STUB/" + nodeId_2 + "/property/actions", "DELETE");
-        Assert.assertEquals(200, httpResponseCode.intValue());
-
-        // Check node2
-        result = getJsonResult(baseURL + "nodes");
-        jt = new JSONTokener(result);
-        json = new JSONObject(jt);
-        node = getJsonInstance(json, "nodeProperties", nodeId_2);
-        Assert.assertNotNull(node);
-        testNodeProperties(node, nodeId_2, nodeType, timestamp_1, timestampName_1, null, capabilitiesValue_1,
-                tablesValue_1, buffersValue_1);
-
         // Test add property to node
-        // Add Tier and Bandwidth property to node1
+        // Add Tier and Description property to node1
         result = getJsonResult(baseURL + "node/STUB/" + nodeId_1 + "/property/tier/1001", "PUT");
-        Assert.assertEquals(201, httpResponseCode.intValue());
-        result = getJsonResult(baseURL + "node/STUB/" + nodeId_1 + "/property/bandwidth/1002", "PUT");
-        Assert.assertEquals(201, httpResponseCode.intValue());
+        Assert.assertEquals(200, httpResponseCode.intValue());
+        result = getJsonResult(baseURL + "node/STUB/" + nodeId_1 + "/property/description/node1", "PUT");
+        Assert.assertEquals(200, httpResponseCode.intValue());
 
         // Test for first node
         result = getJsonResult(baseURL + "nodes");
@@ -527,7 +500,7 @@ public class NorthboundIT {
         node = getJsonInstance(json, "nodeProperties", nodeId_1);
         Assert.assertNotNull(node);
         Assert.assertEquals(1001, node.getJSONObject("properties").getJSONObject("tier").getInt("tierValue"));
-        Assert.assertEquals(1002, node.getJSONObject("properties").getJSONObject("bandwidth").getInt("bandwidthValue"));
+        Assert.assertEquals("node1", node.getJSONObject("properties").getJSONObject("description").getString("descriptionValue"));
 
         // Test delete nodeConnector property
         // Delete state property of nodeconnector1
index d3b0235..d6d9be9 100644 (file)
@@ -9,6 +9,7 @@
 package org.opendaylight.controller.switchmanager.northbound;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
@@ -33,7 +34,6 @@ import org.codehaus.enunciate.jaxrs.TypeHint;
 import org.opendaylight.controller.containermanager.IContainerManager;
 import org.opendaylight.controller.northbound.commons.RestMessages;
 import org.opendaylight.controller.northbound.commons.exception.InternalServerErrorException;
-import org.opendaylight.controller.northbound.commons.exception.ResourceConflictException;
 import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException;
 import org.opendaylight.controller.northbound.commons.exception.ServiceUnavailableException;
 import org.opendaylight.controller.northbound.commons.exception.UnauthorizedException;
@@ -45,7 +45,9 @@ import org.opendaylight.controller.sal.core.Property;
 import org.opendaylight.controller.sal.utils.GlobalConstants;
 import org.opendaylight.controller.sal.utils.ServiceHelper;
 import org.opendaylight.controller.sal.utils.Status;
+import org.opendaylight.controller.sal.utils.StatusCode;
 import org.opendaylight.controller.switchmanager.ISwitchManager;
+import org.opendaylight.controller.switchmanager.SwitchConfig;
 
 /**
  * The class provides Northbound REST APIs to access the nodes, node connectors
@@ -121,6 +123,10 @@ public class SwitchNorthbound {
             @ResponseCode(code = 503, condition = "One or more of Controller Services are unavailable") })
     public Nodes getNodes(@PathParam("containerName") String containerName) {
 
+        if (!isValidContainer(containerName)) {
+            throw new ResourceNotFoundException("Container " + containerName + " does not exist.");
+        }
+
         if (!NorthboundUtils.isAuthorized(
                 getUserName(), containerName, Privilege.READ, this)) {
             throw new UnauthorizedException(
@@ -155,7 +161,13 @@ public class SwitchNorthbound {
     }
 
     /**
-     * Add a Name/Tier property to a node
+     * Add a Name, Tier and Forwarding mode property to a node.
+     *
+     * <pre>
+     * Example Request:
+     *  http://localhost:8080/controller/nb/v2/switch/red/node/OF/00:00:00:00:00:03/property/description/Switch3
+     *  (Valid properties that can be configured are: description, forwarding(only for default container) and tier)
+     * </pre>
      *
      * @param containerName
      *            Name of the Container
@@ -181,7 +193,10 @@ public class SwitchNorthbound {
     @TypeHint(Response.class)
     @StatusCodes({
             @ResponseCode(code = 200, condition = "Operation successful"),
-            @ResponseCode(code = 404, condition = "The Container Name or nodeId or configuration name is not found"),
+            @ResponseCode(code = 400, condition = "The nodeId or configuration is invalid"),
+            @ResponseCode(code = 404, condition = "The Container Name or node or configuration name is not found"),
+            @ResponseCode(code = 406, condition = "The property cannot be configured in non-default container"),
+            @ResponseCode(code = 409, condition = "Unable to update configuration due to cluster conflict"),
             @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") })
     public Response addNodeProperty(
             @PathParam("containerName") String containerName,
@@ -190,14 +205,15 @@ public class SwitchNorthbound {
             @PathParam("propName") String propName,
             @PathParam("propValue") String propValue) {
 
+        if (!isValidContainer(containerName)) {
+            throw new ResourceNotFoundException("Container " + containerName + " does not exist.");
+        }
         if (!NorthboundUtils.isAuthorized(
                 getUserName(), containerName, Privilege.WRITE, this)) {
             throw new UnauthorizedException(
                     "User is not authorized to perform this operation on container "
                             + containerName);
         }
-        handleDefaultDisabled(containerName);
-
         ISwitchManager switchManager = getIfSwitchManagerService(containerName);
         if (switchManager == null) {
             throw new ServiceUnavailableException("Switch Manager "
@@ -206,20 +222,27 @@ public class SwitchNorthbound {
 
         handleNodeAvailability(containerName, nodeType, nodeId);
         Node node = Node.fromString(nodeType, nodeId);
-
         Property prop = switchManager.createProperty(propName, propValue);
         if (prop == null) {
-            throw new ResourceNotFoundException(
-                    RestMessages.INVALIDDATA.toString());
-        }
-
-        switchManager.setNodeProp(node, prop);
-        return Response.status(Response.Status.CREATED).build();
+            throw new ResourceNotFoundException("Property with name " + propName + " does not exist.");
+        }
+        SwitchConfig switchConfig = switchManager.getSwitchConfig(node.toString());
+        Map<String, Property> nodeProperties = (switchConfig == null) ? new HashMap<String, Property>()
+                : new HashMap<String, Property>(switchConfig.getNodeProperties());
+        nodeProperties.put(prop.getName(), prop);
+        SwitchConfig newSwitchConfig = new SwitchConfig(node.toString(), nodeProperties);
+        Status status = switchManager.updateNodeConfig(newSwitchConfig);
+        return NorthboundUtils.getResponse(status);
     }
 
     /**
      * Delete a property of a node
      *
+     * <pre>
+     * Example Request:
+     *  http://localhost:8080/controller/nb/v2/switch/default/node/OF/00:00:00:00:00:03/property/forwarding
+     * </pre>
+     *
      * @param containerName
      *            Name of the Container
      * @param nodeType
@@ -239,7 +262,9 @@ public class SwitchNorthbound {
     @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
     @StatusCodes({
             @ResponseCode(code = 200, condition = "Operation successful"),
+            @ResponseCode(code = 400, condition = "The nodeId or configuration is invalid"),
             @ResponseCode(code = 404, condition = "The Container Name or nodeId or configuration name is not found"),
+            @ResponseCode(code = 409, condition = "Unable to delete property due to cluster conflict"),
             @ResponseCode(code = 503, condition = "One or more of Controller services are unavailable") })
     public Response deleteNodeProperty(
             @PathParam("containerName") String containerName,
@@ -247,14 +272,15 @@ public class SwitchNorthbound {
             @PathParam("nodeId") String nodeId,
             @PathParam("propertyName") String propertyName) {
 
+        if (!isValidContainer(containerName)) {
+            throw new ResourceNotFoundException("Container " + containerName + " does not exist.");
+        }
         if (!NorthboundUtils.isAuthorized(
                 getUserName(), containerName, Privilege.WRITE, this)) {
             throw new UnauthorizedException(
                     "User is not authorized to perform this operation on container "
                             + containerName);
         }
-        handleDefaultDisabled(containerName);
-
         ISwitchManager switchManager = getIfSwitchManagerService(containerName);
         if (switchManager == null) {
             throw new ServiceUnavailableException("Switch Manager "
@@ -263,11 +289,23 @@ public class SwitchNorthbound {
 
         handleNodeAvailability(containerName, nodeType, nodeId);
         Node node = Node.fromString(nodeType, nodeId);
-        Status ret = switchManager.removeNodeProp(node, propertyName);
-        if (ret.isSuccess()) {
-            return Response.ok().build();
+
+        SwitchConfig switchConfig = switchManager.getSwitchConfig(node.toString());
+        Status status;
+        if (switchConfig == null) {
+            status = new Status(StatusCode.NOTFOUND, "Switch Configuration does not exist");
+        } else {
+            Map<String, Property> nodeProperties = new HashMap<String, Property>(switchConfig.getNodeProperties());
+            if (!nodeProperties.containsKey(propertyName.toLowerCase())) {
+                String msg = "Property " + propertyName + " does not exist or not configured for switch " + nodeId;
+                status = new Status(StatusCode.NOTFOUND, msg);
+            } else {
+                nodeProperties.remove(propertyName.toLowerCase());
+                SwitchConfig newSwitchConfig = new SwitchConfig(node.toString(), nodeProperties);
+                status = switchManager.updateNodeConfig(newSwitchConfig);
+            }
         }
-        throw new ResourceNotFoundException(ret.getDescription());
+        return NorthboundUtils.getResponse(status);
     }
 
     /**
@@ -301,6 +339,9 @@ public class SwitchNorthbound {
             @PathParam("nodeType") String nodeType,
             @PathParam("nodeId") String nodeId) {
 
+        if (!isValidContainer(containerName)) {
+            throw new ResourceNotFoundException("Container " + containerName + " does not exist.");
+        }
         if (!NorthboundUtils.isAuthorized(
                 getUserName(), containerName, Privilege.READ, this)) {
             throw new UnauthorizedException(
@@ -379,6 +420,9 @@ public class SwitchNorthbound {
             @PathParam("propName") String propName,
             @PathParam("propValue") String propValue) {
 
+        if (!isValidContainer(containerName)) {
+            throw new ResourceNotFoundException("Container " + containerName + " does not exist.");
+        }
         if (!NorthboundUtils.isAuthorized(
                 getUserName(), containerName, Privilege.WRITE, this)) {
             throw new UnauthorizedException(
@@ -386,8 +430,6 @@ public class SwitchNorthbound {
                             + containerName);
         }
 
-        handleDefaultDisabled(containerName);
-
         ISwitchManager switchManager = getIfSwitchManagerService(containerName);
         if (switchManager == null) {
             throw new ServiceUnavailableException("Switch Manager "
@@ -452,6 +494,9 @@ public class SwitchNorthbound {
             @PathParam("nodeConnectorId") String nodeConnectorId,
             @PathParam("propertyName") String propertyName) {
 
+        if (!isValidContainer(containerName)) {
+            throw new ResourceNotFoundException("Container " + containerName + " does not exist.");
+        }
         if (!NorthboundUtils.isAuthorized(
                 getUserName(), containerName, Privilege.WRITE, this)) {
             throw new UnauthorizedException(
@@ -459,8 +504,6 @@ public class SwitchNorthbound {
                             + containerName);
         }
 
-        handleDefaultDisabled(containerName);
-
         ISwitchManager switchManager = getIfSwitchManagerService(containerName);
         if (switchManager == null) {
             throw new ServiceUnavailableException("Switch Manager "
@@ -604,6 +647,9 @@ public class SwitchNorthbound {
     public Response saveSwitchConfig(
             @PathParam("containerName") String containerName) {
 
+        if (!isValidContainer(containerName)) {
+            throw new ResourceNotFoundException("Container " + containerName + " does not exist.");
+        }
         if (!NorthboundUtils.isAuthorized(
                 getUserName(), containerName, Privilege.WRITE, this)) {
             throw new UnauthorizedException(
@@ -623,20 +669,6 @@ public class SwitchNorthbound {
         throw new InternalServerErrorException(ret.getDescription());
     }
 
-    private void handleDefaultDisabled(String containerName) {
-        IContainerManager containerManager = (IContainerManager) ServiceHelper
-                .getGlobalInstance(IContainerManager.class, this);
-        if (containerManager == null) {
-            throw new InternalServerErrorException(
-                    RestMessages.INTERNALERROR.toString());
-        }
-        if (containerName.equals(GlobalConstants.DEFAULT.toString())
-                && containerManager.hasNonDefaultContainer()) {
-            throw new ResourceConflictException(
-                    RestMessages.DEFAULTDISABLED.toString());
-        }
-    }
-
     private Node handleNodeAvailability(String containerName, String nodeType,
             String nodeId) {
 
@@ -685,4 +717,20 @@ public class SwitchNorthbound {
         }
     }
 
+    private boolean isValidContainer(String containerName) {
+        if (containerName.equals(GlobalConstants.DEFAULT.toString())) {
+            return true;
+        }
+        IContainerManager containerManager = (IContainerManager) ServiceHelper
+                .getGlobalInstance(IContainerManager.class, this);
+        if (containerManager == null) {
+            throw new InternalServerErrorException(
+                    RestMessages.INTERNALERROR.toString());
+        }
+        if (containerManager.getContainerNames().contains(containerName)) {
+            return true;
+       }
+        return false;
+    }
+
 }
index 4138aa6..92cd5b1 100644 (file)
@@ -10,7 +10,7 @@ import javax.xml.bind.annotation.XmlRootElement;
 @SuppressWarnings("serial")
 public class Description extends Property {
     @XmlElement
-    private String description;
+    private String descriptionValue;
     public static final String propertyName = "description";
 
     /*
@@ -18,20 +18,20 @@ public class Description extends Property {
      */
     private Description() {
         super(propertyName);
-        this.description = null;
+        this.descriptionValue = null;
     }
 
     public Description(String description) {
         super(propertyName);
-        this.description = description;
+        this.descriptionValue = description;
     }
 
     public Description clone() {
-        return new Description(this.description);
+        return new Description(this.descriptionValue);
     }
 
     public String getValue() {
-        return this.description;
+        return this.descriptionValue;
     }
 
     @Override
@@ -39,7 +39,7 @@ public class Description extends Property {
         final int prime = 31;
         int result = super.hashCode();
         result = prime * result
-                + ((description == null) ? 0 : description.hashCode());
+                + ((descriptionValue == null) ? 0 : descriptionValue.hashCode());
         return result;
     }
 
@@ -52,16 +52,16 @@ public class Description extends Property {
         if (getClass() != obj.getClass())
             return false;
         Description other = (Description) obj;
-        if (description == null) {
-            if (other.description != null)
+        if (descriptionValue == null) {
+            if (other.descriptionValue != null)
                 return false;
-        } else if (!description.equals(other.description))
+        } else if (!descriptionValue.equals(other.descriptionValue))
             return false;
         return true;
     }
 
     @Override
     public String toString() {
-        return "Description[" + description + "]";
+        return "Description[" + descriptionValue + "]";
     }
 }
index b83e3a6..c28eb13 100644 (file)
@@ -13,7 +13,7 @@ public class ForwardingMode extends Property {
     private final int modeValue;
     public static final int REACTIVE_FORWARDING = 0;
     public static final int PROACTIVE_FORWARDING = 1;
-    public static final String name = "mode";
+    public static final String name = "forwarding";
 
     /*
      * Private constructor used for JAXB mapping
index 97d3eac..574f6d0 100644 (file)
@@ -32,7 +32,7 @@ import javax.xml.bind.annotation.XmlSeeAlso;
     Latency.class, Bandwidth.class, Tier.class, Actions.class,
     AdvertisedBandwidth.class, Buffers.class, Capabilities.class,
     MacAddress.class, PeerBandwidth.class, SupportedBandwidth.class,
-    Tables.class })
+    Tables.class, Description.class, ForwardingMode.class })
 abstract public class Property implements Serializable, Cloneable {
     private static final long serialVersionUID = 1L;
     private final String name;
index 37798ac..f92e92e 100644 (file)
@@ -116,7 +116,14 @@ public class Devices implements IDaylightWeb {
                 nodeDatum.put("tierName", TierHelper.getTierName(tierNumber) + " (Tier-" + tierNumber + ")");
                 nodeDatum.put("tier", tierNumber + "");
                 String modeStr = "0";
-                ForwardingMode mode = (ForwardingMode) switchManager.getNodeProp(node, ForwardingMode.name);
+                ForwardingMode mode = null;
+                if (!containerName.equals(GlobalConstants.DEFAULT.toString())) {
+                    ISwitchManager switchManagerDefault = (ISwitchManager) ServiceHelper.getInstance(
+                            ISwitchManager.class, GlobalConstants.DEFAULT.toString(), this);
+                    mode = (ForwardingMode) switchManagerDefault.getNodeProp(node, ForwardingMode.name);
+                } else {
+                    mode = (ForwardingMode) switchManager.getNodeProp(node, ForwardingMode.name);
+                }
                 if (mode != null) {
                     modeStr = String.valueOf(mode.getValue());
                 }