aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/onos/apps/vtn/vtnweb
diff options
context:
space:
mode:
Diffstat (limited to 'framework/src/onos/apps/vtn/vtnweb')
-rw-r--r--framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/FlowClassifierWebResource.java127
-rw-r--r--framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/PortChainWebResource.java157
-rw-r--r--framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/PortPairGroupWebResource.java163
-rw-r--r--framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/PortPairWebResource.java166
-rw-r--r--framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/FlowClassifierCodec.java134
-rw-r--r--framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/PortChainCodec.java6
-rw-r--r--framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/PortPairCodec.java94
-rw-r--r--framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/PortPairGroupCodec.java95
-rw-r--r--framework/src/onos/apps/vtn/vtnweb/src/main/webapp/WEB-INF/web.xml4
-rw-r--r--framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/web/PortChainCodecTest.java95
-rw-r--r--framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/web/PortPairCodecTest.java94
-rw-r--r--framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/web/PortPairGroupCodecTest.java93
-rw-r--r--framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/web/SfcCodecContext.java77
-rw-r--r--framework/src/onos/apps/vtn/vtnweb/src/test/resources/org/onosproject/vtnweb/web/portChain.json14
-rw-r--r--framework/src/onos/apps/vtn/vtnweb/src/test/resources/org/onosproject/vtnweb/web/portPair.json9
-rw-r--r--framework/src/onos/apps/vtn/vtnweb/src/test/resources/org/onosproject/vtnweb/web/portPairGroup.json10
16 files changed, 1258 insertions, 80 deletions
diff --git a/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/FlowClassifierWebResource.java b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/FlowClassifierWebResource.java
index 1450e4ef..b0e2f38d 100644
--- a/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/FlowClassifierWebResource.java
+++ b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/FlowClassifierWebResource.java
@@ -15,15 +15,12 @@
*/
package org.onosproject.vtnweb.resources;
-import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR;
-import static org.onlab.util.Tools.nullIsNotFound;
import static javax.ws.rs.core.Response.Status.NOT_FOUND;
+import static javax.ws.rs.core.Response.Status.OK;
+import static org.onlab.util.Tools.nullIsNotFound;
import java.io.IOException;
import java.io.InputStream;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.UUID;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
@@ -36,13 +33,17 @@ import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
+import org.onosproject.rest.AbstractWebResource;
import org.onosproject.vtnrsc.FlowClassifier;
import org.onosproject.vtnrsc.FlowClassifierId;
-import org.onosproject.rest.AbstractWebResource;
-import org.onosproject.vtnrsc.flowClassifier.FlowClassifierService;
-import org.onosproject.vtnrsc.web.FlowClassifierCodec;
+import org.onosproject.vtnrsc.flowclassifier.FlowClassifierService;
+import org.onosproject.vtnweb.web.FlowClassifierCodec;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
/**
@@ -51,73 +52,51 @@ import com.fasterxml.jackson.databind.node.ObjectNode;
@Path("flow_classifiers")
public class FlowClassifierWebResource extends AbstractWebResource {
+ private final Logger log = LoggerFactory.getLogger(FlowClassifierWebResource.class);
+
final FlowClassifierService service = get(FlowClassifierService.class);
- final ObjectNode root = mapper().createObjectNode();
public static final String FLOW_CLASSIFIER_NOT_FOUND = "Flow classifier not found";
/**
- * Get all flow classifiers created. Returns list of all flow classifiers
- * created.
+ * Get all flow classifiers created.
*
* @return 200 OK
*/
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getFlowClassifiers() {
- Iterable<FlowClassifier> flowClassifiers = service.getFlowClassifiers();
+ final Iterable<FlowClassifier> flowClassifiers = service.getFlowClassifiers();
ObjectNode result = new ObjectMapper().createObjectNode();
- result.set("flow_classifiers", new FlowClassifierCodec().encode(flowClassifiers, this));
+ ArrayNode flowClassifierEntry = result.putArray("flow_classifiers");
+ if (flowClassifiers != null) {
+ for (final FlowClassifier flowClassifier : flowClassifiers) {
+ flowClassifierEntry.add(new FlowClassifierCodec().encode(flowClassifier, this));
+ }
+ }
return ok(result.toString()).build();
}
/**
- * Get details of a flow classifier. Returns details of a specified flow
- * classifier id.
+ * Get details of a flow classifier.
*
* @param id flow classifier id
- * @return 200 OK
+ * @return 200 OK , 404 if given identifier does not exist
*/
@GET
@Path("{flow_id}")
@Produces(MediaType.APPLICATION_JSON)
public Response getFlowClassifier(@PathParam("flow_id") String id) {
- if (!service.hasFlowClassifier(FlowClassifierId.flowClassifierId(UUID.fromString(id)))) {
+ if (!service.hasFlowClassifier(FlowClassifierId.of(id))) {
return Response.status(NOT_FOUND).entity(FLOW_CLASSIFIER_NOT_FOUND).build();
}
- FlowClassifier flowClassifier = nullIsNotFound(
- service.getFlowClassifier(FlowClassifierId.flowClassifierId(UUID.fromString(id))),
+ FlowClassifier flowClassifier = nullIsNotFound(service.getFlowClassifier(FlowClassifierId.of(id)),
FLOW_CLASSIFIER_NOT_FOUND);
ObjectNode result = new ObjectMapper().createObjectNode();
result.set("flow_classifier", new FlowClassifierCodec().encode(flowClassifier, this));
- return ok(result.toString()).build();
- }
- /**
- * Creates and stores a new flow classifier.
- *
- * @param flowClassifierId flow classifier identifier
- * @param stream flow classifier from JSON
- * @return status of the request - CREATED if the JSON is correct,
- * BAD_REQUEST if the JSON is invalid
- */
- @POST
- @Path("{flow_id}")
- @Consumes(MediaType.APPLICATION_JSON)
- @Produces(MediaType.APPLICATION_JSON)
- public Response createFlowClassifier(@PathParam("flow_id") String flowClassifierId, InputStream stream) {
- URI location;
- try {
- ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
-
- FlowClassifier flowClassifier = codec(FlowClassifier.class).decode(jsonTree, this);
- service.createFlowClassifier(flowClassifier);
- location = new URI(flowClassifierId);
- } catch (IOException | URISyntaxException ex) {
- throw new IllegalArgumentException(ex);
- }
- return Response.created(location).build();
+ return ok(result.toString()).build();
}
/**
@@ -125,32 +104,32 @@ public class FlowClassifierWebResource extends AbstractWebResource {
*
* @param stream flow classifier from JSON
* @return status of the request - CREATED if the JSON is correct,
- * BAD_REQUEST if the JSON is invalid
+ * BAD_REQUEST if the JSON is invalid
*/
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response createFlowClassifier(InputStream stream) {
- URI location;
try {
- ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
-
- FlowClassifier flowClassifier = codec(FlowClassifier.class).decode(jsonTree, this);
- service.createFlowClassifier(flowClassifier);
- location = new URI(flowClassifier.flowClassifierId().toString());
- } catch (IOException | URISyntaxException ex) {
+ ObjectMapper mapper = new ObjectMapper();
+ ObjectNode jsonTree = (ObjectNode) mapper.readTree(stream);
+ JsonNode flow = jsonTree.get("flow_classifier");
+
+ FlowClassifier flowClassifier = new FlowClassifierCodec().decode((ObjectNode) flow, this);
+ Boolean issuccess = nullIsNotFound(service.createFlowClassifier(flowClassifier), FLOW_CLASSIFIER_NOT_FOUND);
+ return Response.status(OK).entity(issuccess.toString()).build();
+ } catch (IOException ex) {
+ log.error("Exception while creating flow classifier {}.", ex.toString());
throw new IllegalArgumentException(ex);
}
- return Response.created(location).build();
}
/**
- * Update details of a flow classifier. Update details of a specified flow
- * classifier id.
+ * Update details of a flow classifier.
*
* @param id flow classifier id
* @param stream InputStream
- * @return 200 OK
+ * @return 200 OK, 404 if given identifier does not exist
*/
@PUT
@Path("{flow_id}")
@@ -158,35 +137,29 @@ public class FlowClassifierWebResource extends AbstractWebResource {
@Consumes(MediaType.APPLICATION_JSON)
public Response updateFlowClassifier(@PathParam("flow_id") String id, final InputStream stream) {
try {
- ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
- FlowClassifier flowClassifier = codec(FlowClassifier.class).decode(jsonTree, this);
+
+ JsonNode jsonTree = mapper().readTree(stream);
+ JsonNode flow = jsonTree.get("flow_classifier");
+ FlowClassifier flowClassifier = new FlowClassifierCodec().decode((ObjectNode) flow, this);
Boolean result = nullIsNotFound(service.updateFlowClassifier(flowClassifier), FLOW_CLASSIFIER_NOT_FOUND);
- if (!result) {
- return Response.status(204).entity(FLOW_CLASSIFIER_NOT_FOUND).build();
- }
- return Response.status(203).entity(result.toString()).build();
- } catch (Exception e) {
- return Response.status(INTERNAL_SERVER_ERROR).entity(e.toString()).build();
+ return Response.status(OK).entity(result.toString()).build();
+ } catch (IOException e) {
+ log.error("Update flow classifier failed because of exception {}.", e.toString());
+ throw new IllegalArgumentException(e);
}
}
/**
- * Delete details of a flow classifier. Delete details of a specified flow
- * classifier id.
+ * Delete details of a flow classifier.
*
* @param id flow classifier id
- * @return 200 OK
- * @throws IOException when input doesn't match.
*/
@Path("{flow_id}")
@DELETE
- public Response deleteFlowClassifier(@PathParam("flow_id") String id) throws IOException {
- try {
- FlowClassifierId flowClassifierId = FlowClassifierId.flowClassifierId(UUID.fromString(id));
- service.removeFlowClassifier(flowClassifierId);
- return Response.status(201).entity("SUCCESS").build();
- } catch (Exception e) {
- return Response.status(INTERNAL_SERVER_ERROR).entity(e.toString()).build();
- }
+ public void deleteFlowClassifier(@PathParam("flow_id") String id) {
+ log.debug("Deletes flow classifier by identifier {}.", id);
+ FlowClassifierId flowClassifierId = FlowClassifierId.of(id);
+ Boolean issuccess = nullIsNotFound(service.removeFlowClassifier(flowClassifierId), FLOW_CLASSIFIER_NOT_FOUND);
+
}
}
diff --git a/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/PortChainWebResource.java b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/PortChainWebResource.java
new file mode 100644
index 00000000..db12bcc7
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/PortChainWebResource.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnweb.resources;
+
+import static javax.ws.rs.core.Response.Status.NOT_FOUND;
+import static javax.ws.rs.core.Response.Status.OK;
+import static org.onlab.util.Tools.nullIsNotFound;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+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.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.onosproject.rest.AbstractWebResource;
+import org.onosproject.vtnrsc.PortChain;
+import org.onosproject.vtnrsc.PortChainId;
+import org.onosproject.vtnrsc.portchain.PortChainService;
+import org.onosproject.vtnweb.web.PortChainCodec;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+/**
+ * Query and program port chain.
+ */
+
+@Path("port_chains")
+public class PortChainWebResource extends AbstractWebResource {
+
+ private final Logger log = LoggerFactory.getLogger(PortChainWebResource.class);
+ private final PortChainService service = get(PortChainService.class);
+ public static final String PORT_CHAIN_NOT_FOUND = "Port chain not found";
+ public static final String PORT_CHAIN_ID_EXIST = "Port chain exists";
+ public static final String PORT_CHAIN_ID_NOT_EXIST = "Port chain does not exist with identifier";
+
+ /**
+ * Get details of all port chains created.
+ *
+ * @return 200 OK
+ */
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response getPortChains() {
+ Iterable<PortChain> portChains = service.getPortChains();
+ ObjectNode result = new ObjectMapper().createObjectNode();
+ result.set("port_chains", new PortChainCodec().encode(portChains, this));
+ return ok(result).build();
+ }
+
+ /**
+ * Get details of a specified port chain id.
+ *
+ * @param id port chain id
+ * @return 200 OK, 404 if given identifier does not exist
+ */
+ @GET
+ @Path("{chain_id}")
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response getPortPain(@PathParam("chain_id") String id) {
+
+ if (!service.exists(PortChainId.of(id))) {
+ return Response.status(NOT_FOUND).entity(PORT_CHAIN_NOT_FOUND).build();
+ }
+ PortChain portChain = nullIsNotFound(service.getPortChain(PortChainId.of(id)),
+ PORT_CHAIN_NOT_FOUND);
+ ObjectNode result = new ObjectMapper().createObjectNode();
+ result.set("port_chain", new PortChainCodec().encode(portChain, this));
+ return ok(result).build();
+ }
+
+ /**
+ * Creates a new port chain.
+ *
+ * @param stream port chain from JSON
+ * @return status of the request - CREATED if the JSON is correct,
+ * BAD_REQUEST if the JSON is invalid
+ */
+ @POST
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response createPortChain(InputStream stream) {
+ try {
+ ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
+ PortChain portChain = codec(PortChain.class).decode(jsonTree, this);
+ Boolean issuccess = nullIsNotFound(service.createPortChain(portChain), PORT_CHAIN_NOT_FOUND);
+ return Response.status(OK).entity(issuccess.toString()).build();
+ } catch (IOException e) {
+ log.error("Exception while creating port chain {}.", e.toString());
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ /**
+ * Update details of a specified port chain id.
+ *
+ * @param id port chain id
+ * @param stream port chain json
+ * @return 200 OK, 404 if given identifier does not exist
+ */
+ @PUT
+ @Path("{chain_id}")
+ @Produces(MediaType.APPLICATION_JSON)
+ @Consumes(MediaType.APPLICATION_JSON)
+ public Response updatePortPain(@PathParam("chain_id") String id,
+ final InputStream stream) {
+ try {
+ ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
+ PortChain portChain = codec(PortChain.class).decode(jsonTree, this);
+ Boolean result = nullIsNotFound(service.updatePortChain(portChain), PORT_CHAIN_NOT_FOUND);
+ return Response.status(OK).entity(result.toString()).build();
+ } catch (IOException e) {
+ log.error("Update port chain failed because of exception {}.", e.toString());
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ /**
+ * Delete details of a specified port chain id.
+ *
+ * @param id port chain id
+ */
+ @Path("{chain_id}")
+ @DELETE
+ public void deletePortPain(@PathParam("chain_id") String id) {
+ log.debug("Deletes port chain by identifier {}.", id);
+ PortChainId portChainId = PortChainId.of(id);
+
+ Boolean issuccess = nullIsNotFound(service.removePortChain(portChainId), PORT_CHAIN_NOT_FOUND);
+ if (!issuccess) {
+ log.debug("Port Chain identifier {} does not exist", id);
+ }
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/PortPairGroupWebResource.java b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/PortPairGroupWebResource.java
new file mode 100644
index 00000000..69daad37
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/PortPairGroupWebResource.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.vtnweb.resources;
+
+import static javax.ws.rs.core.Response.Status.NOT_FOUND;
+import static javax.ws.rs.core.Response.Status.OK;
+import static org.onlab.util.Tools.nullIsNotFound;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+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.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.onosproject.rest.AbstractWebResource;
+import org.onosproject.vtnrsc.PortPairGroup;
+import org.onosproject.vtnrsc.PortPairGroupId;
+import org.onosproject.vtnrsc.portpairgroup.PortPairGroupService;
+import org.onosproject.vtnweb.web.PortPairGroupCodec;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+/**
+ * Query and program port pair group.
+ */
+
+@Path("port_pair_groups")
+public class PortPairGroupWebResource extends AbstractWebResource {
+
+ private final Logger log = LoggerFactory.getLogger(PortPairGroupWebResource.class);
+ private final PortPairGroupService service = get(PortPairGroupService.class);
+ public static final String PORT_PAIR_GROUP_NOT_FOUND = "Port pair group not found";
+ public static final String PORT_PAIR_GROUP_ID_EXIST = "Port pair group exists";
+ public static final String PORT_PAIR_GROUP_ID_NOT_EXIST = "Port pair group does not exist with identifier";
+
+ /**
+ * Get details of all port pair groups created.
+ *
+ * @return 200 OK
+ */
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response getPortPairGroups() {
+ Iterable<PortPairGroup> portPairGroups = service.getPortPairGroups();
+ ObjectNode result = new ObjectMapper().createObjectNode();
+ result.set("port_pair_groups", new PortPairGroupCodec().encode(portPairGroups, this));
+ return ok(result).build();
+ }
+
+ /**
+ * Get details of a specified port pair group id.
+ *
+ * @param id port pair group id
+ * @return 200 OK, 404 if given identifier does not exist
+ */
+ @GET
+ @Path("{group_id}")
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response getPortPairGroup(@PathParam("group_id") String id) {
+
+ if (!service.exists(PortPairGroupId.of(id))) {
+ return Response.status(NOT_FOUND)
+ .entity(PORT_PAIR_GROUP_NOT_FOUND).build();
+ }
+ PortPairGroup portPairGroup = nullIsNotFound(service.getPortPairGroup(PortPairGroupId.of(id)),
+ PORT_PAIR_GROUP_NOT_FOUND);
+
+ ObjectNode result = new ObjectMapper().createObjectNode();
+ result.set("port_pair_group", new PortPairGroupCodec().encode(portPairGroup, this));
+ return ok(result).build();
+ }
+
+ /**
+ * Creates a new port pair group.
+ *
+ * @param stream port pair group from JSON
+ * @return status of the request - CREATED if the JSON is correct,
+ * BAD_REQUEST if the JSON is invalid
+ */
+ @POST
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response createPortPairGroup(InputStream stream) {
+
+ try {
+ ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
+
+ PortPairGroup portPairGroup = codec(PortPairGroup.class).decode(jsonTree, this);
+ Boolean issuccess = nullIsNotFound(service.createPortPairGroup(portPairGroup),
+ PORT_PAIR_GROUP_NOT_FOUND);
+ return Response.status(OK).entity(issuccess.toString()).build();
+ } catch (IOException e) {
+ log.error("Exception while creating port pair group {}.", e.toString());
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ /**
+ * Update details of a specified port pair group id.
+ *
+ * @param id port pair group id
+ * @param stream port pair group from json
+ * @return 200 OK, 404 if given identifier does not exist
+ */
+ @PUT
+ @Path("{group_id}")
+ @Produces(MediaType.APPLICATION_JSON)
+ @Consumes(MediaType.APPLICATION_JSON)
+ public Response updatePortPairGroup(@PathParam("group_id") String id,
+ final InputStream stream) {
+ try {
+ ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
+ PortPairGroup portPairGroup = codec(PortPairGroup.class).decode(jsonTree, this);
+ Boolean isSuccess = nullIsNotFound(service.updatePortPairGroup(portPairGroup), PORT_PAIR_GROUP_NOT_FOUND);
+ return Response.status(OK).entity(isSuccess.toString()).build();
+ } catch (IOException e) {
+ log.error("Update port pair group failed because of exception {}.", e.toString());
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ /**
+ * Delete details of a specified port pair group id.
+ *
+ * @param id port pair group id
+ */
+ @Path("{group_id}")
+ @DELETE
+ public void deletePortPairGroup(@PathParam("group_id") String id) {
+ log.debug("Deletes port pair group by identifier {}.", id);
+ PortPairGroupId portPairGroupId = PortPairGroupId.of(id);
+ Boolean issuccess = nullIsNotFound(service.removePortPairGroup(portPairGroupId),
+ PORT_PAIR_GROUP_NOT_FOUND);
+ if (!issuccess) {
+ log.debug("Port pair group identifier {} does not exist", id);
+ }
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/PortPairWebResource.java b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/PortPairWebResource.java
new file mode 100644
index 00000000..b9012898
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/PortPairWebResource.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.vtnweb.resources;
+
+import static javax.ws.rs.core.Response.Status.NOT_FOUND;
+import static javax.ws.rs.core.Response.Status.OK;
+import static org.onlab.util.Tools.nullIsNotFound;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+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.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.onosproject.rest.AbstractWebResource;
+import org.onosproject.vtnrsc.PortPair;
+import org.onosproject.vtnrsc.PortPairId;
+import org.onosproject.vtnrsc.portpair.PortPairService;
+import org.onosproject.vtnweb.web.PortPairCodec;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+/**
+ * Query and program port pair.
+ */
+@Path("port_pairs")
+public class PortPairWebResource extends AbstractWebResource {
+
+ private final Logger log = LoggerFactory.getLogger(PortPairWebResource.class);
+ private final PortPairService service = get(PortPairService.class);
+ public static final String PORT_PAIR_NOT_FOUND = "Port pair not found";
+ public static final String PORT_PAIR_ID_EXIST = "Port pair exists";
+ public static final String PORT_PAIR_ID_NOT_EXIST = "Port pair does not exist with identifier";
+
+ /**
+ * Get details of all port pairs created.
+ *
+ * @return 200 OK
+ */
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response getPortPairs() {
+ Iterable<PortPair> portPairs = service.getPortPairs();
+ ObjectNode result = new ObjectMapper().createObjectNode();
+ ArrayNode portPairEntry = result.putArray("port_pairs");
+ if (portPairs != null) {
+ for (final PortPair portPair : portPairs) {
+ portPairEntry.add(new PortPairCodec().encode(portPair, this));
+ }
+ }
+ return ok(result.toString()).build();
+ }
+
+ /**
+ * Get details of a specified port pair id.
+ *
+ * @param id port pair id
+ * @return 200 OK, 404 if given identifier does not exist
+ */
+ @GET
+ @Path("{pair_id}")
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response getPortPair(@PathParam("pair_id") String id) {
+
+ if (!service.exists(PortPairId.of(id))) {
+ return Response.status(NOT_FOUND).entity(PORT_PAIR_NOT_FOUND).build();
+ }
+ PortPair portPair = nullIsNotFound(service.getPortPair(PortPairId.of(id)), PORT_PAIR_NOT_FOUND);
+ ObjectNode result = new ObjectMapper().createObjectNode();
+ result.set("port_pair", new PortPairCodec().encode(portPair, this));
+ return ok(result.toString()).build();
+ }
+
+ /**
+ * Creates a new port pair.
+ *
+ * @param stream port pair from JSON
+ * @return status of the request - CREATED if the JSON is correct,
+ * BAD_REQUEST if the JSON is invalid
+ */
+ @POST
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response createPortPair(InputStream stream) {
+ try {
+ ObjectMapper mapper = new ObjectMapper();
+ ObjectNode jsonTree = (ObjectNode) mapper.readTree(stream);
+ JsonNode port = jsonTree.get("port_pair");
+ PortPair portPair = new PortPairCodec().decode((ObjectNode) port, this);
+ Boolean isSuccess = nullIsNotFound(service.createPortPair(portPair), PORT_PAIR_NOT_FOUND);
+ return Response.status(OK).entity(isSuccess.toString()).build();
+ } catch (IOException e) {
+ log.error("Exception while creating port pair {}.", e.toString());
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ /**
+ * Update details of a specified port pair id.
+ *
+ * @param id port pair id
+ * @param stream port pair from json
+ * @return 200 OK, 404 if the given identifier does not exist
+ */
+ @PUT
+ @Path("{pair_id}")
+ @Produces(MediaType.APPLICATION_JSON)
+ @Consumes(MediaType.APPLICATION_JSON)
+ public Response updatePortPair(@PathParam("pair_id") String id,
+ final InputStream stream) {
+ try {
+ ObjectMapper mapper = new ObjectMapper();
+ ObjectNode jsonTree = (ObjectNode) mapper.readTree(stream);
+ JsonNode port = jsonTree.get("port_pair");
+ PortPair portPair = new PortPairCodec().decode((ObjectNode) port, this);
+ Boolean isSuccess = nullIsNotFound(service.updatePortPair(portPair), PORT_PAIR_NOT_FOUND);
+ return Response.status(OK).entity(isSuccess.toString()).build();
+ } catch (IOException e) {
+ log.error("Update port pair failed because of exception {}.", e.toString());
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ /**
+ * Delete details of a specified port pair id.
+ *
+ * @param id port pair id
+ */
+ @Path("{pair_id}")
+ @DELETE
+ public void deletePortPair(@PathParam("pair_id") String id) {
+
+ PortPairId portPairId = PortPairId.of(id);
+ Boolean isSuccess = nullIsNotFound(service.removePortPair(portPairId), PORT_PAIR_NOT_FOUND);
+ if (!isSuccess) {
+ log.debug("Port pair identifier {} does not exist", id);
+ }
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/FlowClassifierCodec.java b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/FlowClassifierCodec.java
new file mode 100644
index 00000000..a18ca362
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/FlowClassifierCodec.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnweb.web;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onlab.util.Tools.nullIsIllegal;
+
+import org.onlab.packet.IpPrefix;
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.vtnrsc.DefaultFlowClassifier;
+import org.onosproject.vtnrsc.FlowClassifier;
+import org.onosproject.vtnrsc.FlowClassifierId;
+import org.onosproject.vtnrsc.TenantId;
+import org.onosproject.vtnrsc.VirtualPortId;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+/**
+ * Flow Classifier JSON codec.
+ */
+public final class FlowClassifierCodec extends JsonCodec<FlowClassifier> {
+
+ private static final String FLOW_CLASSIFIER_ID = "id";
+ private static final String TENANT_ID = "tenant_id";
+ private static final String NAME = "name";
+ private static final String DESCRIPTION = "description";
+ private static final String ETHER_TYPE = "ethertype";
+ private static final String PROTOCOL = "protocol";
+ private static final String MIN_SRC_PORT_RANGE = "source_port_range_min";
+ private static final String MAX_SRC_PORT_RANGE = "source_port_range_max";
+ private static final String MIN_DST_PORT_RANGE = "destination_port_range_min";
+ private static final String MAX_DST_PORT_RANGE = "destination_port_range_max";
+ private static final String SRC_IP_PREFIX = "source_ip_prefix";
+ private static final String DST_IP_PREFIX = "destination_ip_prefix";
+ private static final String SRC_PORT = "logical_source_port";
+ private static final String DST_PORT = "logical_destination_port";
+ private static final String MISSING_MEMBER_MESSAGE = " member is required in Flow Classifier.";
+
+ @Override
+ public FlowClassifier decode(ObjectNode json, CodecContext context) {
+ if (json == null || !json.isObject()) {
+ return null;
+ }
+
+ FlowClassifier.Builder resultBuilder = new DefaultFlowClassifier.Builder();
+
+ String flowClassifierId = nullIsIllegal(json.get(FLOW_CLASSIFIER_ID),
+ FLOW_CLASSIFIER_ID + MISSING_MEMBER_MESSAGE).asText();
+ resultBuilder.setFlowClassifierId(FlowClassifierId.of(flowClassifierId));
+
+ String tenantId = nullIsIllegal(json.get(TENANT_ID), TENANT_ID + MISSING_MEMBER_MESSAGE).asText();
+ resultBuilder.setTenantId(TenantId.tenantId(tenantId));
+
+ String flowClassiferName = nullIsIllegal(json.get(NAME), NAME + MISSING_MEMBER_MESSAGE).asText();
+ resultBuilder.setName(flowClassiferName);
+
+ String flowClassiferDescription = (json.get(DESCRIPTION)).asText();
+ resultBuilder.setDescription(flowClassiferDescription);
+
+ String etherType = nullIsIllegal(json.get(ETHER_TYPE), ETHER_TYPE + MISSING_MEMBER_MESSAGE).asText();
+ resultBuilder.setEtherType(etherType);
+
+ String protocol = (json.get(PROTOCOL)).asText();
+ resultBuilder.setProtocol(protocol);
+
+ int minSrcPortRange = (json.get(MIN_SRC_PORT_RANGE)).asInt();
+ resultBuilder.setMinSrcPortRange(minSrcPortRange);
+
+ int maxSrcPortRange = (json.get(MAX_SRC_PORT_RANGE)).asInt();
+ resultBuilder.setMaxSrcPortRange(maxSrcPortRange);
+
+ int minDstPortRange = (json.get(MIN_DST_PORT_RANGE)).asInt();
+ resultBuilder.setMinDstPortRange(minDstPortRange);
+
+ int maxDstPortRange = (json.get(MAX_DST_PORT_RANGE)).asInt();
+ resultBuilder.setMaxDstPortRange(maxDstPortRange);
+
+ String srcIpPrefix = (json.get(SRC_IP_PREFIX)).asText();
+ if (!srcIpPrefix.isEmpty()) {
+ resultBuilder.setSrcIpPrefix(IpPrefix.valueOf(srcIpPrefix));
+ }
+
+ String dstIpPrefix = (json.get(DST_IP_PREFIX)).asText();
+ if (!dstIpPrefix.isEmpty()) {
+ resultBuilder.setDstIpPrefix(IpPrefix.valueOf(dstIpPrefix));
+ }
+
+ String srcPort = json.get(SRC_PORT) != null ? (json.get(SRC_PORT)).asText() : "";
+ if (!srcPort.isEmpty()) {
+ resultBuilder.setSrcPort(VirtualPortId.portId(srcPort));
+ }
+
+ String dstPort = json.get(DST_PORT) != null ? (json.get(DST_PORT)).asText() : "";
+ if (!dstPort.isEmpty()) {
+ resultBuilder.setDstPort(VirtualPortId.portId(dstPort));
+ }
+ return resultBuilder.build();
+ }
+
+ @Override
+ public ObjectNode encode(FlowClassifier flowClassifier, CodecContext context) {
+ checkNotNull(flowClassifier, "flowClassifier cannot be null");
+ ObjectNode result = context.mapper().createObjectNode()
+ .put(FLOW_CLASSIFIER_ID, flowClassifier.flowClassifierId().toString())
+ .put(TENANT_ID, flowClassifier.tenantId().toString())
+ .put(NAME, flowClassifier.name())
+ .put(DESCRIPTION, flowClassifier.description())
+ .put(ETHER_TYPE, flowClassifier.etherType())
+ .put(PROTOCOL, flowClassifier.protocol())
+ .put(MIN_SRC_PORT_RANGE, flowClassifier.minSrcPortRange())
+ .put(MAX_SRC_PORT_RANGE, flowClassifier.maxSrcPortRange())
+ .put(MIN_DST_PORT_RANGE, flowClassifier.minDstPortRange())
+ .put(MAX_DST_PORT_RANGE, flowClassifier.maxDstPortRange())
+ .put(SRC_IP_PREFIX, flowClassifier.srcIpPrefix().toString())
+ .put(DST_IP_PREFIX, flowClassifier.dstIpPrefix().toString())
+ .put(SRC_PORT, flowClassifier.srcPort().toString())
+ .put(DST_PORT, flowClassifier.dstPort().toString());
+ return result;
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/PortChainCodec.java b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/PortChainCodec.java
index 28da5cd1..1e9cf009 100644
--- a/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/PortChainCodec.java
+++ b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/PortChainCodec.java
@@ -59,7 +59,7 @@ public final class PortChainCodec extends JsonCodec<PortChain> {
String id = nullIsIllegal(json.get(ID),
ID + MISSING_MEMBER_MESSAGE).asText();
- resultBuilder.setId(PortChainId.portChainId(id));
+ resultBuilder.setId(PortChainId.of(id));
String tenantId = nullIsIllegal(json.get(TENANT_ID),
TENANT_ID + MISSING_MEMBER_MESSAGE).asText();
@@ -76,14 +76,14 @@ public final class PortChainCodec extends JsonCodec<PortChain> {
ArrayNode arrayNode = (ArrayNode) json.path(PORT_PAIR_GROUPS);
if (arrayNode != null) {
List<PortPairGroupId> list = Lists.newArrayList();
- arrayNode.forEach(i -> list.add(PortPairGroupId.portPairGroupId(i.asText())));
+ arrayNode.forEach(i -> list.add(PortPairGroupId.of(i.asText())));
resultBuilder.setPortPairGroups(list);
}
arrayNode = (ArrayNode) json.path(FLOW_CLASSIFIERS);
if (arrayNode != null) {
List<FlowClassifierId> list = Lists.newArrayList();
- arrayNode.forEach(i -> list.add(FlowClassifierId.flowClassifierId(UUID.fromString(i.asText()))));
+ arrayNode.forEach(i -> list.add(FlowClassifierId.of(UUID.fromString(i.asText()))));
resultBuilder.setFlowClassifiers(list);
}
diff --git a/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/PortPairCodec.java b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/PortPairCodec.java
new file mode 100644
index 00000000..691536f4
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/PortPairCodec.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnweb.web;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onlab.util.Tools.nullIsIllegal;
+
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.core.CoreService;
+import org.onosproject.vtnrsc.DefaultPortPair;
+import org.onosproject.vtnrsc.PortPair;
+import org.onosproject.vtnrsc.PortPairId;
+import org.onosproject.vtnrsc.TenantId;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+/**
+ * Port Pair JSON codec.
+ */
+public final class PortPairCodec extends JsonCodec<PortPair> {
+
+ private static final String ID = "id";
+ private static final String TENANT_ID = "tenant_id";
+ private static final String NAME = "name";
+ private static final String DESCRIPTION = "description";
+ private static final String INGRESS = "ingress";
+ private static final String EGRESS = "egress";
+ private static final String MISSING_MEMBER_MESSAGE =
+ " member is required in PortPair";
+
+ @Override
+ public PortPair decode(ObjectNode json, CodecContext context) {
+ if (json == null || !json.isObject()) {
+ return null;
+ }
+
+ PortPair.Builder resultBuilder = new DefaultPortPair.Builder();
+
+ CoreService coreService = context.getService(CoreService.class);
+
+ String id = nullIsIllegal(json.get(ID),
+ ID + MISSING_MEMBER_MESSAGE).asText();
+ resultBuilder.setId(PortPairId.of(id));
+
+ String tenantId = nullIsIllegal(json.get(TENANT_ID),
+ TENANT_ID + MISSING_MEMBER_MESSAGE).asText();
+ resultBuilder.setTenantId(TenantId.tenantId(tenantId));
+
+ String name = nullIsIllegal(json.get(NAME),
+ NAME + MISSING_MEMBER_MESSAGE).asText();
+ resultBuilder.setName(name);
+
+ String description = nullIsIllegal(json.get(DESCRIPTION),
+ DESCRIPTION + MISSING_MEMBER_MESSAGE).asText();
+ resultBuilder.setDescription(description);
+
+ String ingressPort = nullIsIllegal(json.get(INGRESS),
+ INGRESS + MISSING_MEMBER_MESSAGE).asText();
+ resultBuilder.setIngress(ingressPort);
+
+ String egressPort = nullIsIllegal(json.get(EGRESS),
+ EGRESS + MISSING_MEMBER_MESSAGE).asText();
+ resultBuilder.setEgress(egressPort);
+
+ return resultBuilder.build();
+ }
+
+ @Override
+ public ObjectNode encode(PortPair portPair, CodecContext context) {
+ checkNotNull(portPair, "port pair cannot be null");
+ ObjectNode result = context.mapper().createObjectNode()
+ .put(ID, portPair.portPairId().toString())
+ .put(TENANT_ID, portPair.tenantId().toString())
+ .put(NAME, portPair.name())
+ .put(DESCRIPTION, portPair.description())
+ .put(INGRESS, portPair.ingress())
+ .put(EGRESS, portPair.egress());
+ return result;
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/PortPairGroupCodec.java b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/PortPairGroupCodec.java
new file mode 100644
index 00000000..b5ae266b
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/PortPairGroupCodec.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.vtnweb.web;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onlab.util.Tools.nullIsIllegal;
+
+import java.util.List;
+
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.core.CoreService;
+import org.onosproject.vtnrsc.DefaultPortPairGroup;
+import org.onosproject.vtnrsc.PortPairGroup;
+import org.onosproject.vtnrsc.PortPairGroupId;
+import org.onosproject.vtnrsc.PortPairId;
+import org.onosproject.vtnrsc.TenantId;
+
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.google.common.collect.Lists;
+
+/**
+ * Port Pair Group JSON codec.
+ */
+public final class PortPairGroupCodec extends JsonCodec<PortPairGroup> {
+
+ private static final String ID = "id";
+ private static final String TENANT_ID = "tenant_id";
+ private static final String NAME = "name";
+ private static final String DESCRIPTION = "description";
+ private static final String PORT_PAIRS = "port_pairs";
+ private static final String MISSING_MEMBER_MESSAGE =
+ " member is required in PortPairGroup";
+
+ @Override
+ public PortPairGroup decode(ObjectNode json, CodecContext context) {
+ if (json == null || !json.isObject()) {
+ return null;
+ }
+
+ PortPairGroup.Builder resultBuilder = new DefaultPortPairGroup.Builder();
+
+ CoreService coreService = context.getService(CoreService.class);
+
+ String id = nullIsIllegal(json.get(ID),
+ ID + MISSING_MEMBER_MESSAGE).asText();
+ resultBuilder.setId(PortPairGroupId.of(id));
+
+ String tenantId = nullIsIllegal(json.get(TENANT_ID),
+ TENANT_ID + MISSING_MEMBER_MESSAGE).asText();
+ resultBuilder.setTenantId(TenantId.tenantId(tenantId));
+
+ String name = nullIsIllegal(json.get(NAME),
+ NAME + MISSING_MEMBER_MESSAGE).asText();
+ resultBuilder.setName(name);
+
+ String description = nullIsIllegal(json.get(DESCRIPTION),
+ DESCRIPTION + MISSING_MEMBER_MESSAGE).asText();
+ resultBuilder.setDescription(description);
+
+ List<PortPairId> list = Lists.newArrayList();
+ ArrayNode arrayNode = (ArrayNode) json.path(PORT_PAIRS);
+ arrayNode.forEach(i -> list.add(PortPairId.of(i.asText())));
+ resultBuilder.setPortPairs(list);
+
+ return resultBuilder.build();
+ }
+
+ @Override
+ public ObjectNode encode(PortPairGroup portPairGroup, CodecContext context) {
+ checkNotNull(portPairGroup, "port pair group cannot be null");
+ ObjectNode result = context.mapper().createObjectNode()
+ .put(ID, portPairGroup.portPairGroupId().toString())
+ .put(TENANT_ID, portPairGroup.tenantId().toString())
+ .put(NAME, portPairGroup.name())
+ .put(DESCRIPTION, portPairGroup.description())
+ .put(PORT_PAIRS, portPairGroup.portPairs().toString());
+ return result;
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnweb/src/main/webapp/WEB-INF/web.xml b/framework/src/onos/apps/vtn/vtnweb/src/main/webapp/WEB-INF/web.xml
index 4cc12455..97337960 100644
--- a/framework/src/onos/apps/vtn/vtnweb/src/main/webapp/WEB-INF/web.xml
+++ b/framework/src/onos/apps/vtn/vtnweb/src/main/webapp/WEB-INF/web.xml
@@ -33,6 +33,10 @@
org.onosproject.vtnweb.resources.TenantNetworkWebResource,
org.onosproject.vtnweb.resources.SubnetWebResource,
org.onosproject.vtnweb.resources.VirtualPortWebResource
+ org.onosproject.vtnweb.resources.FlowClassifierWebResource
+ org.onosproject.vtnweb.resources.PortChainWebResource
+ org.onosproject.vtnweb.resources.PortPairGroupWebResource
+ org.onosproject.vtnweb.resources.PortPairWebResource
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
diff --git a/framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/web/PortChainCodecTest.java b/framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/web/PortChainCodecTest.java
new file mode 100644
index 00000000..02681db3
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/web/PortChainCodecTest.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnweb.web;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.vtnrsc.PortChain;
+import org.onosproject.vtnrsc.PortChainId;
+import org.onosproject.vtnrsc.TenantId;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+/**
+ * Flow rule codec unit tests.
+ */
+public class PortChainCodecTest {
+
+ SfcCodecContext context;
+ JsonCodec<PortChain> portChainCodec;
+ /**
+ * Sets up for each test. Creates a context and fetches the flow rule
+ * codec.
+ */
+ @Before
+ public void setUp() {
+ context = new SfcCodecContext();
+ portChainCodec = context.codec(PortChain.class);
+ assertThat(portChainCodec, notNullValue());
+ }
+
+ /**
+ * Reads in a rule from the given resource and decodes it.
+ *
+ * @param resourceName resource to use to read the JSON for the rule
+ * @return decoded flow rule
+ * @throws IOException if processing the resource fails
+ */
+ private PortChain getPortChain(String resourceName) throws IOException {
+ InputStream jsonStream = PortChainCodecTest.class
+ .getResourceAsStream(resourceName);
+ ObjectMapper mapper = new ObjectMapper();
+ JsonNode json = mapper.readTree(jsonStream);
+ assertThat(json, notNullValue());
+ PortChain portChain = portChainCodec.decode((ObjectNode) json, context);
+ assertThat(portChain, notNullValue());
+ return portChain;
+ }
+
+ /**
+ * Checks that a simple rule decodes properly.
+ *
+ * @throws IOException if the resource cannot be processed
+ */
+ @Test
+ public void codecPortChainTest() throws IOException {
+
+ PortChain portChain = getPortChain("portChain.json");
+
+ assertThat(portChain, notNullValue());
+
+ PortChainId portChainId = PortChainId.of("1278dcd4-459f-62ed-754b-87fc5e4a6751");
+ TenantId tenantId = TenantId.tenantId("d382007aa9904763a801f68ecf065cf5");
+
+ assertThat(portChain.portChainId().toString(), is(portChainId.toString()));
+ assertThat(portChain.name(), is("PC2"));
+ assertThat(portChain.tenantId().toString(), is(tenantId.toString()));
+ assertThat(portChain.description(), is("Two flows and two port-pair-groups"));
+
+ assertThat(portChain.flowClassifiers(), notNullValue());
+ assertThat(portChain.portPairGroups(), notNullValue());
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/web/PortPairCodecTest.java b/framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/web/PortPairCodecTest.java
new file mode 100644
index 00000000..7651e098
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/web/PortPairCodecTest.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnweb.web;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.vtnrsc.PortPair;
+import org.onosproject.vtnrsc.PortPairId;
+import org.onosproject.vtnrsc.TenantId;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+/**
+ * Port pair codec unit tests.
+ */
+public class PortPairCodecTest {
+
+ SfcCodecContext context;
+ JsonCodec<PortPair> portPairCodec;
+ /**
+ * Sets up for each test. Creates a context and fetches the port pair
+ * codec.
+ */
+ @Before
+ public void setUp() {
+ context = new SfcCodecContext();
+ portPairCodec = context.codec(PortPair.class);
+ assertThat(portPairCodec, notNullValue());
+ }
+
+ /**
+ * Reads in a port pair from the given resource and decodes it.
+ *
+ * @param resourceName resource to use to read the JSON for the port pair
+ * @return decoded port pair
+ * @throws IOException if processing the resource fails
+ */
+ private PortPair getPortPair(String resourceName) throws IOException {
+ InputStream jsonStream = PortPairCodecTest.class
+ .getResourceAsStream(resourceName);
+ ObjectMapper mapper = new ObjectMapper();
+ JsonNode json = mapper.readTree(jsonStream);
+ assertThat(json, notNullValue());
+ PortPair portPair = portPairCodec.decode((ObjectNode) json, context);
+ assertThat(portPair, notNullValue());
+ return portPair;
+ }
+
+ /**
+ * Checks that a simple port pair decodes properly.
+ *
+ * @throws IOException if the resource cannot be processed
+ */
+ @Test
+ public void codecPortPairTest() throws IOException {
+
+ PortPair portPair = getPortPair("portPair.json");
+
+ assertThat(portPair, notNullValue());
+
+ PortPairId portPairId = PortPairId.of("78dcd363-fc23-aeb6-f44b-56dc5e2fb3ae");
+ TenantId tenantId = TenantId.tenantId("d382007aa9904763a801f68ecf065cf5");
+
+ assertThat(portPair.portPairId().toString(), is(portPairId.toString()));
+ assertThat(portPair.name(), is("PP1"));
+ assertThat(portPair.tenantId().toString(), is(tenantId.toString()));
+ assertThat(portPair.description(), is("SF-A"));
+ assertThat(portPair.ingress().toString(), is("dace4513-24fc-4fae-af4b-321c5e2eb3d1"));
+ assertThat(portPair.egress().toString(), is("aef3478a-4a56-2a6e-cd3a-9dee4e2ec345"));
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/web/PortPairGroupCodecTest.java b/framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/web/PortPairGroupCodecTest.java
new file mode 100644
index 00000000..de2ee001
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/web/PortPairGroupCodecTest.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnweb.web;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.vtnrsc.PortPairGroup;
+import org.onosproject.vtnrsc.PortPairGroupId;
+import org.onosproject.vtnrsc.TenantId;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+/**
+ * Flow rule codec unit tests.
+ */
+public class PortPairGroupCodecTest {
+
+ SfcCodecContext context;
+ JsonCodec<PortPairGroup> portPairGroupCodec;
+ /**
+ * Sets up for each test. Creates a context and fetches the flow rule
+ * codec.
+ */
+ @Before
+ public void setUp() {
+ context = new SfcCodecContext();
+ portPairGroupCodec = context.codec(PortPairGroup.class);
+ assertThat(portPairGroupCodec, notNullValue());
+ }
+
+ /**
+ * Reads in a rule from the given resource and decodes it.
+ *
+ * @param resourceName resource to use to read the JSON for the rule
+ * @return decoded flow rule
+ * @throws IOException if processing the resource fails
+ */
+ private PortPairGroup getPortPairGroup(String resourceName) throws IOException {
+ InputStream jsonStream = PortPairGroupCodecTest.class
+ .getResourceAsStream(resourceName);
+ ObjectMapper mapper = new ObjectMapper();
+ JsonNode json = mapper.readTree(jsonStream);
+ assertThat(json, notNullValue());
+ PortPairGroup portPairGroup = portPairGroupCodec.decode((ObjectNode) json, context);
+ assertThat(portPairGroup, notNullValue());
+ return portPairGroup;
+ }
+
+ /**
+ * Checks that a simple rule decodes properly.
+ *
+ * @throws IOException if the resource cannot be processed
+ */
+ @Test
+ public void codecPortPairGroupTest() throws IOException {
+
+ PortPairGroup portPairGroup = getPortPairGroup("portPairGroup.json");
+
+ assertThat(portPairGroup, notNullValue());
+
+ PortPairGroupId portPairGroupId = PortPairGroupId.of("4512d643-24fc-4fae-af4b-321c5e2eb3d1");
+ TenantId tenantId = TenantId.tenantId("d382007aa9904763a801f68ecf065cf5");
+
+ assertThat(portPairGroup.portPairGroupId().toString(), is(portPairGroupId.toString()));
+ assertThat(portPairGroup.name(), is("PG1"));
+ assertThat(portPairGroup.tenantId().toString(), is(tenantId.toString()));
+ assertThat(portPairGroup.description(), is("Two port-pairs"));
+ assertThat(portPairGroup.portPairs(), notNullValue());
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/web/SfcCodecContext.java b/framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/web/SfcCodecContext.java
new file mode 100644
index 00000000..fe9d7995
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/web/SfcCodecContext.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnweb.web;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.vtnrsc.FlowClassifier;
+import org.onosproject.vtnrsc.PortChain;
+import org.onosproject.vtnrsc.PortPair;
+import org.onosproject.vtnrsc.PortPairGroup;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+/**
+ * Mock codec context for use in codec unit tests.
+ */
+public class SfcCodecContext implements CodecContext {
+
+ private final ObjectMapper mapper = new ObjectMapper();
+ private final Map<Class<?>, JsonCodec> codecs = new ConcurrentHashMap<>();
+
+ /**
+ * Constructs a new mock codec context.
+ */
+ public SfcCodecContext() {
+ codecs.clear();
+ registerCodec(PortPair.class, new PortPairCodec());
+ registerCodec(PortChain.class, new PortChainCodec());
+ registerCodec(PortPairGroup.class, new PortPairGroupCodec());
+ registerCodec(FlowClassifier.class, new FlowClassifierCodec());
+ }
+
+ @Override
+ public ObjectMapper mapper() {
+ return mapper;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T> T getService(Class<T> serviceClass) {
+ // TODO
+ return null;
+ }
+
+ /**
+ * Registers the specified JSON codec for the given entity class.
+ *
+ * @param entityClass entity class
+ * @param codec JSON codec
+ * @param <T> entity type
+ */
+ public <T> void registerCodec(Class<T> entityClass, JsonCodec<T> codec) {
+ codecs.putIfAbsent(entityClass, codec);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T> JsonCodec<T> codec(Class<T> entityClass) {
+ return codecs.get(entityClass);
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnweb/src/test/resources/org/onosproject/vtnweb/web/portChain.json b/framework/src/onos/apps/vtn/vtnweb/src/test/resources/org/onosproject/vtnweb/web/portChain.json
new file mode 100644
index 00000000..07a1bc21
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnweb/src/test/resources/org/onosproject/vtnweb/web/portChain.json
@@ -0,0 +1,14 @@
+{
+ "id": "1278dcd4-459f-62ed-754b-87fc5e4a6751",
+ "name": "PC2",
+ "tenant_id": "d382007aa9904763a801f68ecf065cf5",
+ "description": "Two flows and two port-pair-groups",
+ "flow_classifiers": [
+ "456a4a34-2e9c-14ae-37fb-765feae2eb05",
+ "4a334cd4-fe9c-4fae-af4b-321c5e2eb051"
+ ],
+ "port_pair_groups": [
+ "4512d643-24fc-4fae-af4b-321c5e2eb3d1",
+ "4a634d49-76dc-4fae-af4b-321c5e23d651"
+ ]
+}
diff --git a/framework/src/onos/apps/vtn/vtnweb/src/test/resources/org/onosproject/vtnweb/web/portPair.json b/framework/src/onos/apps/vtn/vtnweb/src/test/resources/org/onosproject/vtnweb/web/portPair.json
new file mode 100644
index 00000000..f858c88c
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnweb/src/test/resources/org/onosproject/vtnweb/web/portPair.json
@@ -0,0 +1,9 @@
+{
+ "id": "78dcd363-fc23-aeb6-f44b-56dc5e2fb3ae",
+ "name": "PP1",
+ "tenant_id": "d382007aa9904763a801f68ecf065cf5",
+ "description": "SF-A",
+ "ingress": "dace4513-24fc-4fae-af4b-321c5e2eb3d1",
+ "egress": "aef3478a-4a56-2a6e-cd3a-9dee4e2ec345"
+}
+
diff --git a/framework/src/onos/apps/vtn/vtnweb/src/test/resources/org/onosproject/vtnweb/web/portPairGroup.json b/framework/src/onos/apps/vtn/vtnweb/src/test/resources/org/onosproject/vtnweb/web/portPairGroup.json
new file mode 100644
index 00000000..e19a66fc
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnweb/src/test/resources/org/onosproject/vtnweb/web/portPairGroup.json
@@ -0,0 +1,10 @@
+{
+ "id": "4512d643-24fc-4fae-af4b-321c5e2eb3d1",
+ "name": "PG1",
+ "tenant_id": "d382007aa9904763a801f68ecf065cf5",
+ "description": "Two port-pairs",
+ "port_pairs": [
+ "875dfeda-43ed-23fe-454b-764feab2c342",
+ "78dcd363-fc23-aeb6-f44b-56dc5e2fb3ae"
+ ]
+}