From: Pramila Singh Date: Thu, 8 Aug 2013 20:59:25 +0000 (-0700) Subject: Fix to set/delete Switch Configuration using Northbound API X-Git-Tag: releasepom-0.1.0~216 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=e34a8ad4271e43fd903523a04ccf2a44ff4995f2 Fix to set/delete Switch Configuration using Northbound API Change-Id: Ib3d7184a64bba4341637052ae96ae104073a64bc Signed-off-by: Pramila Singh --- diff --git a/opendaylight/containermanager/api/src/main/java/org/opendaylight/controller/containermanager/IContainerManager.java b/opendaylight/containermanager/api/src/main/java/org/opendaylight/controller/containermanager/IContainerManager.java index b956d76a2e..89c0c0b217 100644 --- a/opendaylight/containermanager/api/src/main/java/org/opendaylight/controller/containermanager/IContainerManager.java +++ b/opendaylight/containermanager/api/src/main/java/org/opendaylight/controller/containermanager/IContainerManager.java @@ -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(); diff --git a/opendaylight/northbound/integrationtest/src/test/java/org/opendaylight/controller/northbound/integrationtest/NorthboundIT.java b/opendaylight/northbound/integrationtest/src/test/java/org/opendaylight/controller/northbound/integrationtest/NorthboundIT.java index dff17ff086..553505f4a3 100644 --- a/opendaylight/northbound/integrationtest/src/test/java/org/opendaylight/controller/northbound/integrationtest/NorthboundIT.java +++ b/opendaylight/northbound/integrationtest/src/test/java/org/opendaylight/controller/northbound/integrationtest/NorthboundIT.java @@ -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 diff --git a/opendaylight/northbound/switchmanager/src/main/java/org/opendaylight/controller/switchmanager/northbound/SwitchNorthbound.java b/opendaylight/northbound/switchmanager/src/main/java/org/opendaylight/controller/switchmanager/northbound/SwitchNorthbound.java index d3b023512b..d6d9be9e9f 100644 --- a/opendaylight/northbound/switchmanager/src/main/java/org/opendaylight/controller/switchmanager/northbound/SwitchNorthbound.java +++ b/opendaylight/northbound/switchmanager/src/main/java/org/opendaylight/controller/switchmanager/northbound/SwitchNorthbound.java @@ -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. + * + *
+     * 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)
+     * 
* * @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 nodeProperties = (switchConfig == null) ? new HashMap() + : new HashMap(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 * + *
+     * Example Request:
+     *  http://localhost:8080/controller/nb/v2/switch/default/node/OF/00:00:00:00:00:03/property/forwarding
+     * 
+ * * @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 nodeProperties = new HashMap(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; + } + } diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Description.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Description.java index 4138aa6c34..92cd5b12e4 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Description.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Description.java @@ -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 + "]"; } } diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/ForwardingMode.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/ForwardingMode.java index b83e3a696d..c28eb13d55 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/ForwardingMode.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/ForwardingMode.java @@ -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 diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Property.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Property.java index 97d3eac808..574f6d0238 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Property.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/core/Property.java @@ -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; diff --git a/opendaylight/web/devices/src/main/java/org/opendaylight/controller/devices/web/Devices.java b/opendaylight/web/devices/src/main/java/org/opendaylight/controller/devices/web/Devices.java index 37798ac137..f92e92ec17 100644 --- a/opendaylight/web/devices/src/main/java/org/opendaylight/controller/devices/web/Devices.java +++ b/opendaylight/web/devices/src/main/java/org/opendaylight/controller/devices/web/Devices.java @@ -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()); }