Northbound api cleanup for Subnets 37/1037/1
authorDiti Bhatia <dibhatia@cisco.com>
Thu, 29 Aug 2013 06:34:45 +0000 (23:34 -0700)
committerDiti Bhatia <dibhatia@cisco.com>
Thu, 29 Aug 2013 06:37:22 +0000 (23:37 -0700)
Change-Id: I55f9bfdad8d35a19e2c19a10933d57714b69da88
Signed-off-by: Diti Bhatia <dibhatia@cisco.com>
opendaylight/northbound/integrationtest/src/test/java/org/opendaylight/controller/northbound/integrationtest/NorthboundIT.java
opendaylight/northbound/subnets/src/main/java/org/opendaylight/controller/subnets/northbound/SubnetsNorthbound.java [new file with mode: 0644]
opendaylight/northbound/subnets/src/main/java/org/opendaylight/controller/subnets/northbound/SubnetsNorthboundJAXRS.java [deleted file]
opendaylight/northbound/subnets/src/main/java/org/opendaylight/controller/subnets/northbound/SubnetsNorthboundRSApplication.java
opendaylight/switchmanager/api/src/main/java/org/opendaylight/controller/switchmanager/SubnetConfig.java

index a39249d4115437a667b2e62708cabf00e8363cb5..b8229cfc5d5ad0896d1558f5a71d3ccc2a426574 100644 (file)
@@ -272,50 +272,99 @@ public class NorthboundIT {
 
         String name1 = "testSubnet1";
         String subnet1 = "1.1.1.1/24";
+
         String name2 = "testSubnet2";
         String subnet2 = "2.2.2.2/24";
+        String[] nodePorts2 = {"2/1", "2/2", "2/3", "2/4"};
+        StringBuilder nodePortsJson2 = new StringBuilder();
+        nodePortsJson2.append(nodePorts2[0] + "," + nodePorts2[1]  + "," + nodePorts2[2] + "," + nodePorts2[3]);
+
+        String name3 = "testSubnet3";
+        String subnet3 = "3.3.3.3/24";
+        String[] nodePorts3 = {"3/1", "3/2", "3/3"};
+        StringBuilder nodePortsJson3 = new StringBuilder();
+        nodePortsJson3.append(nodePorts3[0] + "," + nodePorts3[1]  + "," + nodePorts3[2]);
+        StringBuilder nodePortsJson3_1 = new StringBuilder();
+        nodePortsJson3_1.append(nodePortsJson3).append(",").append(nodePortsJson2);
 
         // Test GET subnets in default container
-        String result = getJsonResult(baseURL + "default");
+        String result = getJsonResult(baseURL + "default/subnet/all");
         JSONTokener jt = new JSONTokener(result);
         JSONObject json = new JSONObject(jt);
         Assert.assertEquals("{}", result);
 
         // Test GET subnet1 expecting 404
-        result = getJsonResult(baseURL + "default/" + name1);
+        result = getJsonResult(baseURL + "default/subnet/" + name1);
         Assert.assertEquals(404, httpResponseCode.intValue());
 
         // Test POST subnet1
-        String queryParameter = new QueryParameter("subnetName", name1).add("subnet", subnet1).getString();
-        result = getJsonResult(baseURL + "default/" + name1 + queryParameter, "POST");
-        Assert.assertEquals(201, httpResponseCode.intValue());
+        JSONObject jo = new JSONObject().append("name", name1).append("subnet", subnet1);
+        // execute HTTP request and verify response code
+        result = getJsonResult(baseURL + "default/subnet/" + name1, "POST", jo.toString());
+        Assert.assertTrue(httpResponseCode == 201);
 
         // Test GET subnet1
-        result = getJsonResult(baseURL + "default/" + name1);
+        result = getJsonResult(baseURL + "default/subnet/" + name1);
         jt = new JSONTokener(result);
         json = new JSONObject(jt);
         Assert.assertEquals(200, httpResponseCode.intValue());
-        Assert.assertEquals(name1, json.getString("@name"));
-        Assert.assertEquals(subnet1, json.getString("@subnet"));
+        Assert.assertEquals(name1, json.getString("name"));
+        Assert.assertEquals(subnet1, json.getString("subnet"));
 
         // Test POST subnet2
-        queryParameter = new QueryParameter("subnetName", name2).add("subnet", subnet2).getString();
-        result = getJsonResult(baseURL + "default/" + name2 + queryParameter, "POST");
+        JSONObject jo2 = new JSONObject().append("name", name2).append("subnet", subnet2);
+        // execute HTTP request and verify response code
+        result = getJsonResult(baseURL + "default/subnet/" + name2, "POST", jo2.toString());
+        Assert.assertEquals(201, httpResponseCode.intValue());
+        // Test POST nodePorts
+        jo2.append("nodePorts", nodePortsJson2);
+        // execute HTTP request and verify response code
+        result = getJsonResult(baseURL + "default/subnet/" + name2 + "/node-ports", "POST", jo2.toString());
+        Assert.assertEquals(200, httpResponseCode.intValue());
+        // Test POST subnet3
+        JSONObject jo3 = new JSONObject().append("name", name3).append("subnet", subnet3);
+        // execute HTTP request and verify response code
+        result = getJsonResult(baseURL + "default/subnet/" + name3, "POST", jo3.toString());
         Assert.assertEquals(201, httpResponseCode.intValue());
+        // Test POST nodePorts
+        jo3.append("nodePorts", nodePortsJson3);
+        // execute HTTP request and verify response code
+        result = getJsonResult(baseURL + "default/subnet/" + name3 + "/node-ports", "POST", jo3.toString());
+        Assert.assertEquals(200, httpResponseCode.intValue());
+        // Test PUT nodePorts
+        jo3.remove("nodePorts");
+        jo3.append("nodePorts", nodePortsJson3_1);
+        result = getJsonResult(baseURL + "default/subnet/" + name3 + "/node-ports", "PUT", jo3.toString());
+        Assert.assertEquals(200, httpResponseCode.intValue());
 
         // Test GET all subnets in default container
-        result = getJsonResult(baseURL + "default");
+        result = getJsonResult(baseURL + "default/subnet/all");
         jt = new JSONTokener(result);
         json = new JSONObject(jt);
         JSONArray subnetConfigArray = json.getJSONArray("subnetConfig");
         JSONObject subnetConfig;
-        Assert.assertEquals(2, subnetConfigArray.length());
+        Assert.assertEquals(3, subnetConfigArray.length());
         for (int i = 0; i < subnetConfigArray.length(); i++) {
             subnetConfig = subnetConfigArray.getJSONObject(i);
-            if (subnetConfig.getString("@name").equals(name1)) {
-                Assert.assertEquals(subnet1, subnetConfig.getString("@subnet"));
-            } else if (subnetConfig.getString("@name").equals(name2)) {
-                Assert.assertEquals(subnet2, subnetConfig.getString("@subnet"));
+            if (subnetConfig.getString("name").equals(name1)) {
+                Assert.assertEquals(subnet1, subnetConfig.getString("subnet"));
+            } else if (subnetConfig.getString("name").equals(name2)) {
+                Assert.assertEquals(subnet2, subnetConfig.getString("subnet"));
+                String[] nodePortsGet2 = subnetConfig.getString("nodePorts").split(",");
+                Assert.assertEquals(nodePorts2[0], nodePortsGet2[0]);
+                Assert.assertEquals(nodePorts2[1], nodePortsGet2[1]);
+                Assert.assertEquals(nodePorts2[2], nodePortsGet2[2]);
+                Assert.assertEquals(nodePorts2[3], nodePortsGet2[3]);
+            } else if (subnetConfig.getString("name").equals(name3)) {
+                Assert.assertEquals(subnet3, subnetConfig.getString("subnet"));
+                String[] nodePortsGet = subnetConfig.getString("nodePorts").split(",");
+                Assert.assertEquals(nodePorts3[0], nodePortsGet[0]);
+                Assert.assertEquals(nodePorts3[1], nodePortsGet[1]);
+                Assert.assertEquals(nodePorts3[2], nodePortsGet[2]);
+                Assert.assertEquals(nodePorts2[0], nodePortsGet[3]);
+                Assert.assertEquals(nodePorts2[1], nodePortsGet[4]);
+                Assert.assertEquals(nodePorts2[2], nodePortsGet[5]);
+                Assert.assertEquals(nodePorts2[3], nodePortsGet[6]);
             } else {
                 // Unexpected config name
                 Assert.assertTrue(false);
@@ -323,14 +372,13 @@ public class NorthboundIT {
         }
 
         // Test DELETE subnet1
-        result = getJsonResult(baseURL + "default/" + name1, "DELETE");
-        Assert.assertEquals(200, httpResponseCode.intValue());
+        result = getJsonResult(baseURL + "default/subnet/" + name1, "DELETE");
+        Assert.assertEquals(204, httpResponseCode.intValue());
 
         // Test GET deleted subnet1
-        result = getJsonResult(baseURL + "default/" + name1);
+        result = getJsonResult(baseURL + "default/subnet/" + name1);
         Assert.assertEquals(404, httpResponseCode.intValue());
-
-    }
+  }
 
     @Test
     public void testStaticRoutingNorthbound() throws JSONException {
diff --git a/opendaylight/northbound/subnets/src/main/java/org/opendaylight/controller/subnets/northbound/SubnetsNorthbound.java b/opendaylight/northbound/subnets/src/main/java/org/opendaylight/controller/subnets/northbound/SubnetsNorthbound.java
new file mode 100644 (file)
index 0000000..2765072
--- /dev/null
@@ -0,0 +1,642 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  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.subnets.northbound;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+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.core.Context;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.SecurityContext;
+import javax.xml.bind.JAXBElement;
+
+import org.codehaus.enunciate.jaxrs.ResponseCode;
+import org.codehaus.enunciate.jaxrs.StatusCodes;
+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.BadRequestException;
+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;
+import org.opendaylight.controller.northbound.commons.utils.NorthboundUtils;
+import org.opendaylight.controller.sal.authorization.Privilege;
+import org.opendaylight.controller.sal.utils.ServiceHelper;
+import org.opendaylight.controller.sal.utils.Status;
+import org.opendaylight.controller.switchmanager.ISwitchManager;
+import org.opendaylight.controller.switchmanager.SubnetConfig;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Path("/")
+public class SubnetsNorthbound {
+    protected static final Logger logger = LoggerFactory.getLogger(SubnetsNorthbound.class);
+
+    private String username;
+
+    @Context
+    public void setSecurityContext(SecurityContext context) {
+        username = context.getUserPrincipal().getName();
+    }
+
+    protected String getUserName() {
+        return username;
+    }
+
+    private void handleContainerDoesNotExist(String containerName) {
+        IContainerManager containerManager = (IContainerManager) ServiceHelper.getGlobalInstance(
+                IContainerManager.class, this);
+        if (containerManager == null) {
+            throw new ServiceUnavailableException("Container " + RestMessages.NOCONTAINER.toString());
+        }
+
+        List<String> containerNames = containerManager.getContainerNames();
+        for (String cName : containerNames) {
+            if (cName.trim().equalsIgnoreCase(containerName.trim())) {
+                return;
+            }
+        }
+
+        throw new ResourceNotFoundException(containerName + " " + RestMessages.NOCONTAINER.toString());
+    }
+
+    private void handleNameMismatch(String name, String nameinURL) {
+        if (name == null || nameinURL == null) {
+            throw new BadRequestException(RestMessages.INVALIDDATA.toString() + " : Name is null");
+        }
+
+        if (name.equals(nameinURL)) {
+            return;
+        }
+        throw new ResourceConflictException(RestMessages.INVALIDDATA.toString()
+                + " : Name in URL does not match the name in request body");
+    }
+
+    /**
+     * List all the subnets in a given container
+     *
+     * @param containerName
+     *            container in which we want to query the subnets
+     *
+     * @return a List of SubnetConfig
+     *
+     *         <pre>
+     * Example:
+     *
+     * Request URL: http://localhost:8080/controller/nb/v2/subnet/default/subnet/all
+     *
+     * Response in XML:
+     * &lt;subnetConfig&gt;
+     *    &lt;name&gt;subnet1&lt;/name&gt;
+     *    &lt;subnet&gt;30.0.0.1/24&lt;/subnet&gt;
+     *    &lt;nodePorts&gt;1/1&gt;/nodePorts&gt;
+     *    &lt;nodePorts&gt;1/2&gt;/nodePorts&gt;
+     *    &lt;nodePorts&gt;1/3&gt;/nodePorts&gt;
+     * &lt;/subnetConfig&gt;
+     * &lt;subnetConfig&gt;
+     *    &lt;name&gt;subnet2&lt;/name&gt;
+     *    &lt;subnet&gt;20.0.0.1/24&lt;/subnet&gt;
+     *    &lt;nodePorts&gt;2/1&gt;/nodePorts&gt;
+     *    &lt;nodePorts&gt;2/2&gt;/nodePorts&gt;
+     *    &lt;nodePorts&gt;2/3&gt;/nodePorts&gt;
+     * &lt;/subnetConfig&gt;
+     *
+     * Response in JSON:
+     * {
+     *  "name":"subnet1",
+     *  "subnet":"30.0.0.1/24",
+     *  "nodePorts":["1/1","1/2","1/3"]
+     * }
+     * {
+     *  "name":"subnet2",
+     *  "subnet":"20.0.0.1/24",
+     *  "nodePorts":["2/1","2/2","2/3"]
+     * }
+     * </pre>
+     */
+    @Path("/{containerName}/subnet/all")
+    @GET
+    @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+    @StatusCodes({ @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
+            @ResponseCode(code = 404, condition = "The containerName passed was not found"),
+            @ResponseCode(code = 503, condition = "Service unavailable") })
+    @TypeHint(SubnetConfigs.class)
+    public SubnetConfigs listSubnets(@PathParam("containerName") String containerName) {
+
+        handleContainerDoesNotExist(containerName);
+        if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.READ, this)) {
+            throw new UnauthorizedException("User is not authorized to perform this operation on container "
+                    + containerName);
+        }
+         ISwitchManager switchManager = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class, containerName, this);
+        if (switchManager == null) {
+            throw new ServiceUnavailableException("SwitchManager " + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+        return new SubnetConfigs(switchManager.getSubnetsConfigList());
+    }
+
+    /**
+     * List the configuration of a subnet in a given container
+     *
+     * @param containerName
+     *            container in which we want to query the subnet
+     * @param subnetName
+     *            of the subnet being queried
+     *
+     * @return SubnetConfig
+     *
+     *         <pre>
+     * Example:
+     *
+     * Request URL: http://localhost:8080/controller/nb/v2/subnet/default/subnet/subnet1
+     *
+     * Response in XML:
+     * &lt;subnetConfig&gt;
+     *    &lt;name&gt;subnet1&lt;/name&gt;
+     *    &lt;subnet&gt;30.0.0.1/24&lt;/subnet&gt;
+     *    &lt;nodePorts&gt;1/1&gt;/nodePorts&gt;
+     *    &lt;nodePorts&gt;1/2&gt;/nodePorts&gt;
+     *    &lt;nodePorts&gt;1/3&gt;/nodePorts&gt;
+     * &lt;/subnetConfig&gt;
+     *
+     * Response in JSON:
+     * {
+     *  "name":"subnet1",
+     *  "subnet":"30.0.0.1/24",
+     *  "nodePorts":["1/1","1/2","1/3"]
+     * }
+     * </pre>
+     */
+    @Path("/{containerName}/subnet/{subnetName}")
+    @GET
+    @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+    @StatusCodes({ @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
+            @ResponseCode(code = 404, condition = "The containerName or subnetName passed was not found"),
+            @ResponseCode(code = 503, condition = "Service unavailable") })
+    @TypeHint(SubnetConfig.class)
+    public SubnetConfig listSubnet(@PathParam("containerName") String containerName,
+            @PathParam("subnetName") String subnetName) {
+
+        handleContainerDoesNotExist(containerName);
+
+        if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.READ, this)) {
+            throw new UnauthorizedException("User is not authorized to perform this operation on container "
+                    + containerName);
+        }
+        ISwitchManager switchManager = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class, containerName, this);
+        if (switchManager == null) {
+            throw new ServiceUnavailableException("SwitchManager " + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+        SubnetConfig res = switchManager.getSubnetConfig(subnetName);
+        if (res == null) {
+            throw new ResourceNotFoundException(RestMessages.NOSUBNET.toString());
+        } else {
+            return res;
+        }
+    }
+
+    /**
+     * Add a subnet to a container
+     *
+     * @param containerName
+     *            name of the container to which subnet needs to be added
+     * @param subnetName
+     *            name of new subnet to be added
+     * @param subnetConfigData
+     *            the {@link SubnetConfig} structure in request body
+     *
+     * @return Response as dictated by the HTTP Response Status code
+     *
+     *         <pre>
+     * Example:
+     *
+     * Request URL: http://localhost:8080/controller/nb/v2/subnet/default/subnet/subnet1
+     *
+     * Request XML:
+     *  &lt;subnetConfig&gt;
+     *      &lt;name&gt;subnet1&lt;/name&gt;
+     *      &lt;subnet&gt;30.0.0.1/24&lt;/subnet&gt;
+     * &lt;/subnetConfig&gt;
+     *
+     * Request in JSON:
+     * {
+     *  "name":"subnet1",
+     *  "subnet":"30.0.0.1/24"
+     * }
+     * </pre>
+     */
+
+    @Path("/{containerName}/subnet/{subnetName}")
+    @POST
+    @StatusCodes({ @ResponseCode(code = 201, condition = "Subnet created successfully"),
+            @ResponseCode(code = 400, condition = "Invalid data passed"),
+            @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
+            @ResponseCode(code = 409, condition = "Subnet name in url conflicts with name in request body"),
+            @ResponseCode(code = 404, condition = "Container name passed was not found or subnet config is null"),
+            @ResponseCode(code = 500, condition = "Internal Server Error: Addition of subnet failed"),
+            @ResponseCode(code = 503, condition = "Service unavailable") })
+    public Response addSubnet(@PathParam("containerName") String containerName,
+            @PathParam("subnetName") String subnetName,
+            @TypeHint(SubnetConfig.class) JAXBElement<SubnetConfig> subnetConfigData) {
+
+        handleContainerDoesNotExist(containerName);
+
+        if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.WRITE, this)) {
+            throw new UnauthorizedException("User is not authorized to perform this operation on container "
+                    + containerName);
+        }
+        SubnetConfig cfgObject = subnetConfigData.getValue();
+        handleNameMismatch(cfgObject.getName(), subnetName);
+
+        ISwitchManager switchManager = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class, containerName, this);
+        if (switchManager == null) {
+            throw new ServiceUnavailableException("SwitchManager " + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+        Set<String> ports = cfgObject.getNodePorts();
+        SubnetConfig subnetCfg = null;
+        if (ports == null) {
+            subnetCfg = new SubnetConfig(cfgObject.getName(), cfgObject.getSubnet(), new HashSet<String>(0));
+        } else {
+            subnetCfg = cfgObject;
+        }
+
+        Status status = switchManager.addSubnet(subnetCfg);
+
+        if (status.isSuccess()) {
+            NorthboundUtils.auditlog("Subnet Gateway", username, "added", subnetName, containerName);
+            return Response.status(Response.Status.CREATED).build();
+        }
+        return NorthboundUtils.getResponse(status);
+    }
+
+    /**
+     * Delete a subnet from a container
+     *
+     * @param containerName
+     *            name of the container from which subnet needs to be removed
+     * @param subnetName
+     *            name of new subnet to be deleted
+     * @return Response as dictated by the HTTP Response Status code
+     *
+     *         <pre>
+     * Example:
+     *            Request URL: http://localhost:8080/controller/nb/v2/subnet/default/subnet/subnet1
+     *
+     * </pre>
+     */
+    @Path("/{containerName}/subnet/{subnetName}")
+    @DELETE
+    @StatusCodes({ @ResponseCode(code = 204, condition = "No Content"),
+            @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
+            @ResponseCode(code = 404, condition = "The containerName passed was not found"),
+            @ResponseCode(code = 500, condition = "Internal Server Error : Removal of subnet failed"),
+            @ResponseCode(code = 503, condition = "Service unavailable") })
+    public Response removeSubnet(@PathParam("containerName") String containerName,
+            @PathParam("subnetName") String subnetName) {
+
+        handleContainerDoesNotExist(containerName);
+
+        if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.WRITE, this)) {
+            throw new UnauthorizedException("User is not authorized to perform this operation on container "
+                    + containerName);
+        }
+
+        ISwitchManager switchManager = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class, containerName, this);
+        if (switchManager == null) {
+            throw new ServiceUnavailableException("SwitchManager " + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+        Status status = switchManager.removeSubnet(subnetName);
+        if (status.isSuccess()) {
+            NorthboundUtils.auditlog("Subnet Gateway", username, "removed", subnetName, containerName);
+            return Response.status(Response.Status.NO_CONTENT).build();
+        }
+        return NorthboundUtils.getResponse(status);
+    }
+
+    /**
+     * Modify a subnet. For now only changing the port list is allowed.
+     *
+     * @param containerName
+     *            Name of the Container
+     * @param subnetName
+     *            Name of the SubnetConfig to be modified
+     * @param subnetConfigData
+     *            the {@link SubnetConfig} structure in request body
+     *            parameter
+     * @return If the operation is successful or not
+     *
+     *         <pre>
+     * Example:
+     *
+     * Request URL: http://localhost:8080/controller/nb/v2/subnet/default/subnet/subnet1/node-ports
+     *
+     *  Request in XML:
+     *  &lt;subnetConfig&gt;
+     *      &lt;name&gt;subnet1&lt;/name&gt;
+     *      &lt;subnet&gt;30.0.0.1/24&lt;/subnet&gt;
+     *      &lt;nodePorts&gt;1/1&lt;/nodePorts&gt;
+     *      &lt;nodePorts&gt;1/2&lt;/nodePorts&gt;
+     *      &lt;nodePorts&gt;1/3&lt;/nodePorts&gt;
+     * &lt;/subnetConfig&gt;
+     *
+     * Request in JSON:
+     * {
+     *  "name":"subnet1",
+     *  "subnet":"30.0.0.1/24",
+     *  "nodePorts":["1/1","1/2","1/3"]
+     * }
+     * </pre>
+     */
+    @Path("/{containerName}/subnet/{subnetName}/node-ports")
+    @PUT
+    @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+    @StatusCodes({
+            @ResponseCode(code = 200, condition = "Ports replaced successfully"),
+            @ResponseCode(code = 400, condition = "Invalid request to change subnet name or invalid node ports passed"),
+            @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
+            @ResponseCode(code = 409, condition = "Subnet name in url conflicts with name in request body"),
+            @ResponseCode(code = 404, condition = "The containerName or subnetName is not found"),
+            @ResponseCode(code = 500, condition = "Internal server error: Modify ports failed"),
+            @ResponseCode(code = 503, condition = "Service unavailable") })
+    public Response modifySubnet(@PathParam("containerName") String containerName,
+            @PathParam("subnetName") String subnetName,
+            @TypeHint(SubnetConfig.class) JAXBElement<SubnetConfig> subnetConfigData) {
+
+        handleContainerDoesNotExist(containerName);
+
+        if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.WRITE, this)) {
+            throw new UnauthorizedException("User is not authorized to perform this operation on container "
+                    + containerName);
+        }
+        handleNameMismatch(subnetConfigData.getValue().getName(), subnetName);
+
+        ISwitchManager switchManager = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class, containerName,
+                this);
+        if (switchManager == null) {
+            throw new ServiceUnavailableException("SwitchManager " + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+
+        SubnetConfig subnetConf = subnetConfigData.getValue();
+        SubnetConfig existingConf = switchManager.getSubnetConfig(subnetName);
+
+        boolean successful = true;
+
+        // make sure that the name matches an existing subnet and we're not
+        // changing the name or subnet IP/mask
+        if (existingConf == null) {
+            // don't have a subnet by that name
+            return Response.status(Response.Status.NOT_FOUND).build();
+
+        } else if (!existingConf.getName().equals(subnetConf.getName())
+                || !existingConf.getSubnet().equals(subnetConf.getSubnet())) {
+            // can't change the name of a subnet
+            Response.status(Response.Status.BAD_REQUEST).build();
+        } else {
+            // create a set for fast lookups
+            Set<String> newPorts = new HashSet<String>(subnetConf.getNodePorts());
+
+            // go through the current ports and (1) remove ports that aren't
+            // there anymore and (2) remove ports that are still there from the
+            // set of ports to add
+            for (String s : existingConf.getNodePorts()) {
+                if (newPorts.contains(s)) {
+                    newPorts.remove(s);
+                } else {
+                    Status st = switchManager.removePortsFromSubnet(subnetName, s);
+                    successful = successful && st.isSuccess();
+                }
+            }
+
+            // add any remaining ports
+            for (String s : newPorts) {
+                Status st = switchManager.addPortsToSubnet(subnetName, s);
+                successful = successful && st.isSuccess();
+                if (successful) {
+                    NorthboundUtils.auditlog("Subnet Gateway", username, "added", s + " to " + subnetName,
+                            containerName);
+                }
+            }
+        }
+
+        if (successful) {
+            return Response.status(Response.Status.OK).build();
+        }
+        throw new InternalServerErrorException(RestMessages.INTERNALERROR.toString());
+    }
+
+    /**
+     * Add ports to a subnet in the container
+     *
+     * @param containerName
+     *            name of the container that has the subnet to which node ports
+     *            need to be added
+     * @param subnetName
+     *            name of subnet to which node ports need to be added
+     * @param SubnetConfig
+     *            the {@link SubnetConfig} structure in request body
+     * @return Response as dictated by the HTTP Response Status code
+     *
+     *         <pre>
+     * Example:
+     *            Request URL: http://localhost:8080/controller/nb/v2/subnet/default/subnet/subnet1/node-ports
+     *
+     * Request XML:
+     *  &lt;subnetConfig&gt;
+     *      &lt;name&gt;subnet1&lt;/name&gt;
+     *      &lt;subnet&gt;30.0.0.1/24&lt;/subnet&gt;
+     *      &lt;nodePorts&gt;1/1&lt;/nodePorts&gt;
+     *      &lt;nodePorts&gt;1/2&lt;/nodePorts&gt;
+     *      &lt;nodePorts&gt;1/3&lt;/nodePorts&gt;
+     * &lt;/subnetConfig&gt;
+     *
+     * Request in JSON:
+     * {
+     *  "name":"subnet1",
+     *  "subnet":"30.0.0.1/24",
+     *  "nodePorts":["1/1","1/2","1/3"]
+     * }
+     *
+     * </pre>
+     */
+    @Path("/{containerName}/subnet/{subnetName}/node-ports")
+    @POST
+    @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+    @StatusCodes({
+            @ResponseCode(code = 200, condition = "Added node ports to subnet successfully"),
+            @ResponseCode(code = 400, condition = "Invalid request to change subnet name or invalid node ports passed"),
+            @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
+            @ResponseCode(code = 404, condition = "The containerName or subnet is not found"),
+            @ResponseCode(code = 409, condition = "Subnet name in url conflicts with name in request body"),
+            @ResponseCode(code = 500, condition = "Internal server error : Port add failed"),
+            @ResponseCode(code = 503, condition = "Service unavailable") })
+    public Response addNodePorts(@PathParam("containerName") String containerName,
+            @PathParam("subnetName") String subnetName,
+            @TypeHint(SubnetConfig.class) JAXBElement<SubnetConfig> subnetConfigData) {
+
+        handleContainerDoesNotExist(containerName);
+
+        if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.WRITE, this)) {
+            throw new UnauthorizedException("User is not authorized to perform this operation on container "
+                    + containerName);
+        }
+        handleNameMismatch(subnetConfigData.getValue().getName(), subnetName);
+
+        SubnetConfig subnetConf = subnetConfigData.getValue();
+
+        ISwitchManager switchManager = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class, containerName,
+                this);
+        if (switchManager == null) {
+            throw new ServiceUnavailableException("SwitchManager " + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+
+        SubnetConfig existingConf = switchManager.getSubnetConfig(subnetName);
+
+        // make sure that the name matches an existing subnet and we're not
+        // changing the name or subnet IP/mask
+        if (existingConf == null) {
+            // don't have a subnet by that name
+            return Response.status(Response.Status.NOT_FOUND).build();
+        } else if (!existingConf.getName().equals(subnetConf.getName())
+                || !existingConf.getSubnet().equals(subnetConf.getSubnet())) {
+            // can't change the name of a subnet
+            return Response.status(Response.Status.BAD_REQUEST).build();
+        }
+        Status st;
+        boolean successful = true;
+        Set<String> ports = subnetConf.getNodePorts();
+
+        if (ports == null || ports.isEmpty()) {
+            throw new BadRequestException(RestMessages.INVALIDDATA.toString());
+        }
+
+        // add new ports only
+        if (existingConf.getNodePorts() != null) {
+            ports.removeAll(existingConf.getNodePorts());
+        }
+        for (String port : ports) {
+            st = switchManager.addPortsToSubnet(subnetName, port);
+            successful = successful && st.isSuccess();
+            if (successful) {
+                NorthboundUtils.auditlog("Subnet Gateway", username, "added", st + " to " + subnetName, containerName);
+            }
+        }
+        if (successful) {
+            return Response.status(Response.Status.OK).build();
+        }
+        throw new InternalServerErrorException(RestMessages.INTERNALERROR.toString());
+    }
+
+    /**
+     * Delete ports from a subnet in the container
+     *
+     * @param containerName
+     *            name of the container that has the subnet from which node
+     *            ports need to be deleted
+     * @param subnetName
+     *            name of subnet from which node ports need to be deleted
+     * @param subnetConfigData
+     *            SubnetConfig object to be deleted
+     * @return Response as dictated by the HTTP Response Status code
+     *
+     *         <pre>
+     * Example:
+     *            Request URL: http://localhost:8080/controller/nb/v2/subnet/default/subnet/subnet1/node-ports
+     *
+     * Request XML:
+     *  &lt;subnetConfig&gt;
+     *      &lt;name&gt;subnet3&lt;/name&gt;
+     *      &lt;subnet&gt;30.0.0.1/24&lt;/subnet&gt;
+     *      &lt;nodePorts&gt;1/1,1/2,1/3&lt;/nodePorts&gt;
+     * &lt;/subnetConfig&gt;
+     *
+     * Request in JSON:
+     * { "name" : "subnet1",
+     *   "subnet" : "30.0.0.1/24",
+     *    nodePorts : ["1/1,1/2,1/3"]}
+     *
+     * </pre>
+     */
+    @Path("/{containerName}/subnet/{subnetName}/node-ports")
+    @DELETE
+    @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+    @StatusCodes({
+            @ResponseCode(code = 204, condition = "No content"),
+            @ResponseCode(code = 400, condition = "Invalid request to change subnet name or invalid node ports passed"),
+            @ResponseCode(code = 401, condition = "User not authorized to perform this operation"),
+            @ResponseCode(code = 404, condition = "The containerName or subnet is not found"),
+            @ResponseCode(code = 409, condition = "Subnet name in url conflicts with name in request body"),
+            @ResponseCode(code = 500, condition = "Internal server error : Delete node ports failed"),
+            @ResponseCode(code = 503, condition = "Service unavailable") })
+    public Response deleteNodePorts(@PathParam("containerName") String containerName,
+            @PathParam("subnetName") String subnetName,
+            @TypeHint(SubnetConfig.class) JAXBElement<SubnetConfig> subnetConfigData) {
+
+        handleContainerDoesNotExist(containerName);
+
+        if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.WRITE, this)) {
+            throw new UnauthorizedException("User is not authorized to perform this operation on container "
+                    + containerName);
+        }
+        handleNameMismatch(subnetConfigData.getValue().getName(), subnetName);
+
+        SubnetConfig subnetConf = subnetConfigData.getValue();
+
+        if (subnetConf.getNodePorts() == null || subnetConf.getNodePorts().isEmpty()) {
+            throw new BadRequestException(RestMessages.INVALIDDATA.toString() + " : invalid node ports");
+        }
+
+        ISwitchManager switchManager = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class, containerName,
+                this);
+        if (switchManager == null) {
+            throw new ServiceUnavailableException("SwitchManager " + RestMessages.SERVICEUNAVAILABLE.toString());
+        }
+
+        SubnetConfig existingConf = switchManager.getSubnetConfig(subnetName);
+
+        // make sure that the name matches an existing subnet and we're not
+        // changing the name or subnet IP/mask
+        if (existingConf == null) {
+            // don't have a subnet by that name
+            return Response.status(Response.Status.NOT_FOUND).build();
+        } else if (!existingConf.getName().equals(subnetConf.getName())
+                || !existingConf.getSubnet().equals(subnetConf.getSubnet())) {
+            // can't change the name of a subnet
+            return Response.status(Response.Status.BAD_REQUEST).build();
+        }
+        Status st;
+        boolean successful = true;
+        Set<String> ports = subnetConf.getNodePorts();
+
+        // delete existing ports
+        ports.retainAll(existingConf.getNodePorts());
+        for (String port : ports) {
+            st = switchManager.removePortsFromSubnet(subnetName, port);
+            successful = successful && st.isSuccess();
+            if (successful) {
+                NorthboundUtils.auditlog("Subnet Gateway", username, "removed", st + " from " + subnetName,
+                        containerName);
+            }
+        }
+        if (successful) {
+            return Response.status(Response.Status.NO_CONTENT).build();
+        }
+        throw new InternalServerErrorException(RestMessages.INTERNALERROR.toString());
+    }
+}
diff --git a/opendaylight/northbound/subnets/src/main/java/org/opendaylight/controller/subnets/northbound/SubnetsNorthboundJAXRS.java b/opendaylight/northbound/subnets/src/main/java/org/opendaylight/controller/subnets/northbound/SubnetsNorthboundJAXRS.java
deleted file mode 100644 (file)
index 8c555f2..0000000
+++ /dev/null
@@ -1,426 +0,0 @@
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  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.subnets.northbound;
-
-import java.util.HashSet;
-import java.util.Set;
-
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-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.Context;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.SecurityContext;
-import javax.xml.bind.JAXBElement;
-
-import org.codehaus.enunciate.jaxrs.ResponseCode;
-import org.codehaus.enunciate.jaxrs.StatusCodes;
-import org.codehaus.enunciate.jaxrs.TypeHint;
-import org.opendaylight.controller.northbound.commons.RestMessages;
-import org.opendaylight.controller.northbound.commons.exception.InternalServerErrorException;
-import org.opendaylight.controller.northbound.commons.exception.ResourceNotFoundException;
-import org.opendaylight.controller.northbound.commons.exception.UnauthorizedException;
-import org.opendaylight.controller.northbound.commons.utils.NorthboundUtils;
-import org.opendaylight.controller.sal.authorization.Privilege;
-import org.opendaylight.controller.sal.utils.ServiceHelper;
-import org.opendaylight.controller.sal.utils.Status;
-import org.opendaylight.controller.switchmanager.ISwitchManager;
-import org.opendaylight.controller.switchmanager.SubnetConfig;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-@Path("/")
-public class SubnetsNorthboundJAXRS {
-    protected static final Logger logger = LoggerFactory.getLogger(SubnetsNorthboundJAXRS.class);
-
-    private String username;
-
-    @Context
-    public void setSecurityContext(SecurityContext context) {
-        username = context.getUserPrincipal().getName();
-    }
-
-    protected String getUserName() {
-        return username;
-    }
-
-    /**
-     * List all the subnets in a given container
-     *
-     * @param containerName
-     *            container in which we want to query the subnets
-     *
-     * @return a List of SubnetConfig
-     */
-    @Path("/{containerName}")
-    @GET
-    @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
-    @StatusCodes({ @ResponseCode(code = 404, condition = "The containerName passed was not found") })
-    @TypeHint(SubnetConfigs.class)
-    public SubnetConfigs listSubnets(@PathParam("containerName") String containerName) {
-        if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.READ, this)) {
-            throw new UnauthorizedException("User is not authorized to perform this operation on container "
-                    + containerName);
-        }
-        ISwitchManager switchManager = null;
-        switchManager = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class, containerName, this);
-        if (switchManager == null) {
-            throw new ResourceNotFoundException(RestMessages.NOCONTAINER.toString());
-        }
-        return new SubnetConfigs(switchManager.getSubnetsConfigList());
-    }
-
-    /**
-     * List the configuration of a subnet in a given container
-     *
-     * @param containerName
-     *            container in which we want to query the subnet
-     * @param subnetName
-     *            of the subnet being queried
-     *
-     * @return a SubnetConfig
-     */
-    @Path("/{containerName}/{subnetName}")
-    @GET
-    @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
-    @StatusCodes({
-        @ResponseCode(code = 404, condition = "The containerName passed was not found"),
-        @ResponseCode(code = 404, condition = "Subnet does not exist") })
-        @TypeHint(SubnetConfig.class)
-    public SubnetConfig listSubnet(
-        @PathParam("containerName") String containerName,
-        @PathParam("subnetName") String subnetName) {
-
-        if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.READ, this)) {
-            throw new UnauthorizedException("User is not authorized to perform this operation on container "
-                    + containerName);
-        }
-        ISwitchManager switchManager = null;
-        switchManager = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class, containerName, this);
-        if (switchManager == null) {
-            throw new ResourceNotFoundException(RestMessages.NOCONTAINER.toString());
-        }
-        SubnetConfig res = switchManager.getSubnetConfig(subnetName);
-        if (res == null) {
-            throw new ResourceNotFoundException(RestMessages.NOSUBNET.toString());
-        } else {
-            return res;
-        }
-    }
-
-    /**
-     * Add a subnet to a container
-     *
-     * @param containerName
-     *            container in which we want to add/update the subnet
-     * @param subnetName
-     *            that has to be added
-     * @param subnet
-     *            pair default gateway IP/mask that identify the subnet being
-     *            added modified
-     *
-     */
-    @Path("/{containerName}/{subnetName}")
-    @POST
-    @StatusCodes({
-        @ResponseCode(code = 404, condition = "Invalid Data passed"),
-        @ResponseCode(code = 201, condition = "Subnet added"),
-        @ResponseCode(code = 500, condition = "Addition of subnet failed") })
-    public Response addSubnet(
-        @PathParam("containerName") String containerName,
-        @PathParam("subnetName") String subnetName, @QueryParam("subnet") String subnet) {
-
-        if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.WRITE, this)) {
-            throw new UnauthorizedException("User is not authorized to perform this operation on container "
-                    + containerName);
-        }
-        if (subnetName == null) {
-            throw new ResourceNotFoundException(RestMessages.INVALIDDATA.toString());
-        }
-        if (subnet == null) {
-            throw new ResourceNotFoundException(RestMessages.INVALIDDATA.toString());
-        }
-        ISwitchManager switchManager = null;
-        switchManager = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class, containerName, this);
-        if (switchManager == null) {
-            throw new ResourceNotFoundException(RestMessages.NOCONTAINER.toString());
-        }
-
-        SubnetConfig cfgObject = new SubnetConfig(subnetName, subnet, new HashSet<String>(0));
-        Status status = switchManager.addSubnet(cfgObject);
-        if (status.isSuccess()) {
-            NorthboundUtils.auditlog("Subnet Gateway", username, "added", subnetName, containerName);
-            return Response.status(Response.Status.CREATED).build();
-        }
-        throw new InternalServerErrorException(status.getDescription());
-    }
-
-    /**
-     * Delete a subnet from a container
-     *
-     * @param containerName
-     *            container in which we want to delete the subnet by name
-     * @param subnetName
-     *            of the subnet to be remove.
-     *
-     */
-    @Path("/{containerName}/{subnetName}")
-    @DELETE
-    @StatusCodes({
-        @ResponseCode(code = 404, condition = "The containerName passed was not found"),
-        @ResponseCode(code = 500, condition = "Removal of subnet failed") })
-    public Response removeSubnet(
-        @PathParam("containerName") String containerName,
-        @PathParam("subnetName") String subnetName) {
-        if (subnetName == null) {
-            throw new ResourceNotFoundException(RestMessages.INVALIDDATA.toString());
-        }
-
-        if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.WRITE, this)) {
-            throw new UnauthorizedException("User is not authorized to perform this operation on container "
-                    + containerName);
-        }
-
-        ISwitchManager switchManager = null;
-        switchManager = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class, containerName, this);
-        if (switchManager == null) {
-            throw new ResourceNotFoundException(RestMessages.NOCONTAINER.toString());
-        }
-        Status status = switchManager.removeSubnet(subnetName);
-        if (status.isSuccess()) {
-            NorthboundUtils.auditlog("Subnet Gateway", username, "removed", subnetName, containerName);
-            return Response.status(Response.Status.OK).build();
-        }
-        throw new InternalServerErrorException(status.getDescription());
-    }
-
-    /**
-     * Modify a subnet. For now only changing the port list is allowed.
-     *
-     * @param containerName
-     *            Name of the Container
-     * @param name
-     *            Name of the SubnetConfig to be modified
-     * @param subnetConfigData
-     *            the {@link SubnetConfig} structure in JSON passed as a POST
-     *            parameter
-     * @return If the operation is successful or not
-     */
-    @Path("/{containerName}/{subnetName}/modify")
-    @POST
-    @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
-    @StatusCodes({
-        @ResponseCode(code = 202, condition = "Operation successful"),
-        @ResponseCode(code = 400, condition = "Invalid request, i.e., requested changing the subnet name"),
-        @ResponseCode(code = 404, condition = "The containerName or subnetName is not found"),
-        @ResponseCode(code = 500, condition = "Internal server error") })
-    public Response modifySubnet(@PathParam("containerName") String containerName,
-        @PathParam("subnetName") String name,
-        @TypeHint(SubnetConfig.class) JAXBElement<SubnetConfig> subnetConfigData) {
-
-        if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.WRITE, this)) {
-            throw new UnauthorizedException("User is not authorized to perform this operation on container "
-                    + containerName);
-        }
-
-        ISwitchManager switchManager = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class, containerName,
-                this);
-        if (switchManager == null) {
-            throw new ResourceNotFoundException(RestMessages.NOCONTAINER.toString());
-        }
-
-        SubnetConfig subnetConf = subnetConfigData.getValue();
-        SubnetConfig existingConf = switchManager.getSubnetConfig(name);
-
-        boolean successful = true;
-
-        // make sure that the name matches an existing subnet and we're not
-        // changing the name or subnet IP/mask
-        if (existingConf == null) {
-            // don't have a subnet by that name
-            return Response.status(Response.Status.NOT_FOUND).build();
-
-        } else if (!existingConf.getName().equals(subnetConf.getName())
-                || !existingConf.getSubnet().equals(subnetConf.getSubnet())) {
-            // can't change the name of a subnet
-            return Response.status(Response.Status.BAD_REQUEST).build();
-
-        } else {
-            // create a set for fast lookups
-            Set<String> newPorts = new HashSet<String>(subnetConf.getNodePorts());
-
-            // go through the current ports and (1) remove ports that aren't
-            // there anymore and (2) remove ports that are still there from the
-            // set of ports to add
-            for (String s : existingConf.getNodePorts()) {
-                if (newPorts.contains(s)) {
-                    newPorts.remove(s);
-                } else {
-                    Status st = switchManager.removePortsFromSubnet(name, s);
-                    successful = successful && st.isSuccess();
-                }
-            }
-
-            // add any remaining ports
-            for (String s : newPorts) {
-                Status st = switchManager.addPortsToSubnet(name, s);
-                successful = successful && st.isSuccess();
-                if(successful){
-                    NorthboundUtils.auditlog("Subnet Gateway", username, "added", s +" to "+name, containerName);
-                }
-            }
-        }
-
-        if (successful) {
-            return Response.status(Response.Status.ACCEPTED).build();
-        } else {
-            return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
-        }
-    }
-
-    /**
-     *
-     * Add ports to a subnet
-     *
-     * @param containerName
-     *            Name of the Container
-     * @param name
-     *            Name of the SubnetConfig to be modified
-     * @param subnetConfigData
-     *            the {@link SubnetConfig} structure in JSON passed as a POST
-     *            parameter
-     * @return If the operation is successful or not
-     */
-    @Path("/{containerName}/{subnetName}/add")
-    @POST
-    @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
-    @StatusCodes({
-        @ResponseCode(code = 202, condition = "Operation successful"),
-        @ResponseCode(code = 400, condition = "Invalid request"),
-        @ResponseCode(code = 404, condition = "The containerName or subnetName is not found"),
-        @ResponseCode(code = 500, condition = "Internal server error") })
-    public Response addNodePorts(
-            @PathParam("containerName") String containerName,
-            @PathParam("subnetName") String name,
-            @TypeHint(SubnetConfig.class) JAXBElement<SubnetConfig> subnetConfigData) {
-
-        SubnetConfig subnetConf = subnetConfigData.getValue();
-        return addOrDeletePorts(containerName, name, subnetConf, "add");
-    }
-
-    /**
-     *
-     * Delete ports from a subnet
-     *
-     * @param containerName
-     *            Name of the Container
-     * @param name
-     *            Name of the SubnetConfig to be modified
-     * @param subnetConfigData
-     *            the {@link SubnetConfig} structure in JSON passed as a POST
-     *            parameter
-     * @return If the operation is successful or not
-     */
-    @Path("/{containerName}/{subnetName}/delete")
-    @POST
-    @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
-    @StatusCodes({
-        @ResponseCode(code = 202, condition = "Operation successful"),
-        @ResponseCode(code = 400, condition = "Invalid request"),
-        @ResponseCode(code = 404, condition = "The containerName or subnetName is not found"),
-        @ResponseCode(code = 500, condition = "Internal server error") })
-    public Response deleteNodePorts(
-            @PathParam("containerName") String containerName,
-            @PathParam("subnetName") String name,
-            @TypeHint(SubnetConfig.class) JAXBElement<SubnetConfig> subnetConfigData) {
-
-        SubnetConfig subnetConf = subnetConfigData.getValue();
-        return addOrDeletePorts(containerName, name, subnetConf, "delete");
-    }
-
-    /**
-    *
-    * Add/Delete ports to/from a subnet
-    *
-    * @param containerName
-    *            Name of the Container
-    * @param name
-    *            Name of the SubnetConfig to be modified
-    * @param subnetConfig
-    *            the {@link SubnetConfig} structure
-    * @param action
-    *            add or delete
-    * @return If the operation is successful or not
-    */
-    private Response addOrDeletePorts(String containerName, String name, SubnetConfig subnetConf, String action) {
-
-        if (!NorthboundUtils.isAuthorized(getUserName(), containerName, Privilege.WRITE, this)) {
-            throw new UnauthorizedException("User is not authorized to perform this operation on container "
-                    + containerName);
-        }
-
-        ISwitchManager switchManager = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class, containerName,
-                this);
-        if (switchManager == null) {
-            throw new ResourceNotFoundException(RestMessages.NOCONTAINER.toString());
-        }
-
-        SubnetConfig existingConf = switchManager.getSubnetConfig(name);
-
-        // make sure that the name matches an existing subnet and we're not
-        // changing the name or subnet IP/mask
-        if (existingConf == null) {
-            // don't have a subnet by that name
-            return Response.status(Response.Status.NOT_FOUND).build();
-        } else if (!existingConf.getName().equals(subnetConf.getName())
-                || !existingConf.getSubnet().equals(subnetConf.getSubnet())) {
-            // can't change the name of a subnet
-            return Response.status(Response.Status.BAD_REQUEST).build();
-        } else {
-            Status st;
-            boolean successful = true;
-            Set<String> ports = subnetConf.getNodePorts();
-
-            if (action.equals("add")) {
-                // add new ports
-                ports.removeAll(existingConf.getNodePorts());
-                for (String port : ports) {
-                    st = switchManager.addPortsToSubnet(name, port);
-                    successful = successful && st.isSuccess();
-                    if(successful){
-                        NorthboundUtils.auditlog("Subnet Gateway", username, "added",  st +" to "+name, containerName);
-                    }
-                }
-            } else if (action.equals("delete")) {
-                // delete existing ports
-                ports.retainAll(existingConf.getNodePorts());
-                for (String port : ports) {
-                    st = switchManager.removePortsFromSubnet(name, port);
-                    successful = successful && st.isSuccess();
-                    if(successful){
-                        NorthboundUtils.auditlog("Subnet Gateway", username, "removed",  st +" from "+name, containerName);
-                    }
-                }
-            } else {
-                return Response.status(Response.Status.BAD_REQUEST).build();
-            }
-
-            if (successful) {
-                return Response.status(Response.Status.ACCEPTED).build();
-            } else {
-                return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
-            }
-        }
-    }
-}
index 5efe6bad0049a725e68770b15c1239a3dc48c07a..a5eaf94f26ff3d935782fe64a083fc38922ba222 100644 (file)
@@ -9,6 +9,7 @@ package org.opendaylight.controller.subnets.northbound;
 
 import java.util.HashSet;
 import java.util.Set;
+
 import javax.ws.rs.core.Application;
 
 /**
@@ -22,7 +23,7 @@ public class SubnetsNorthboundRSApplication extends Application {
     @Override
     public Set<Class<?>> getClasses() {
         Set<Class<?>> classes = new HashSet<Class<?>>();
-        classes.add(SubnetsNorthboundJAXRS.class);
+        classes.add(SubnetsNorthbound.class);
         return classes;
     }
 }
index 4ed9934b27a3f6d3105c2854c86c48f131fe40c6..36ab101a79a40525549543869f22befef25c679a 100644 (file)
@@ -19,7 +19,6 @@ import java.util.Set;
 
 import javax.xml.bind.annotation.XmlAccessType;
 import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlAttribute;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlRootElement;
 
@@ -42,14 +41,23 @@ public class SubnetConfig implements Cloneable, Serializable {
 
     // Order matters: JSP file expects following fields in the
     // following order
-    @XmlAttribute
+    /**
+     * Name of the subnet
+     */
+    @XmlElement
     private String name;
-    @XmlAttribute
-    private String subnet; // A.B.C.D/MM  Where A.B.C.D is the Default
-                           // Gateway IP (L3) or ARP Querier IP (L2
+    /**
+     * A.B.C.D/MM  Where A.B.C.D is the Default
+     * Gateway IP (L3) or ARP Querier IP (L2)
+     */
+    @XmlElement
+    private String subnet;
+    /**
+     * node ID/port list:
+     *<node-id>/a,b,c-m,r-t,y
+     */
     @XmlElement
-    private Set<String> nodePorts; // datapath ID/port list:
-                                    // xx:xx:xx:xx:xx:xx:xx:xx/a,b,c-m,r-t,y
+    private Set<String> nodePorts;
 
     public SubnetConfig() {
     }
@@ -185,13 +193,13 @@ public class SubnetConfig implements Cloneable, Serializable {
     //NodeConnectors learnt from a string
     private void getNodeConnectorsFromString(String codedNodeConnectors,
             Set<NodeConnector> sp) {
-        if (codedNodeConnectors == null) {
+        if (codedNodeConnectors == null || codedNodeConnectors.isEmpty()) {
             return;
         }
         if (sp == null) {
             return;
         }
-        // codedNodeConnectors = xx:xx:xx:xx:xx:xx:xx:xx/a,b,c-m,r-t,y
+        // codedNodeConnectors = nodeId/a,b,c-m,r-t,y
         String pieces[] = codedNodeConnectors.split("/");
         for (Short port : getPortList(pieces[1])) {
             Node n = Node.fromString(pieces[0]);
@@ -218,7 +226,7 @@ public class SubnetConfig implements Cloneable, Serializable {
     }
 
     public Set<NodeConnector> getNodeConnectors(String codedNodeConnectors) {
-        // codedNodeConnectors = xx:xx:xx:xx:xx:xx:xx:xx/a,b,c-m,r-t,y
+        // codedNodeConnectors = nodeId/a,b,c-m,r-t,y
         Set<NodeConnector> sp = new HashSet<NodeConnector>();
         getNodeConnectorsFromString(codedNodeConnectors, sp);
         return sp;