Jian Li
Committed by Gerrit Code Review

[ONOS-3603] Add getGroupByDeviceIdAndAppCookie method in group REST API

* Add a new method for getting a specific group result
* Add descriptions in swagger doc

Change-Id: I62a476bd2cd774eed157dd3954349eb5aa335db3
......@@ -43,6 +43,8 @@ import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import static org.onlab.util.Tools.nullIsNotFound;
/**
* Query and program group rules.
*/
......@@ -50,6 +52,7 @@ import java.net.URISyntaxException;
@Path("groups")
public class GroupsWebResource extends AbstractWebResource {
public static final String DEVICE_INVALID = "Invalid deviceId in group creation request";
public static final String GROUP_NOT_FOUND = "Group was not found";
final GroupService groupService = get(GroupService.class);
final ObjectNode root = mapper().createObjectNode();
......@@ -57,8 +60,9 @@ public class GroupsWebResource extends AbstractWebResource {
/**
* Returns all groups of all devices.
* @onos.rsModel Groups
*
* @return array of all the groups in the system
* @onos.rsModel Groups
*/
@GET
@Produces(MediaType.APPLICATION_JSON)
......@@ -78,8 +82,8 @@ public class GroupsWebResource extends AbstractWebResource {
* Returns all groups associated with the given device.
*
* @param deviceId device identifier
* @onos.rsModel Groups
* @return array of all the groups in the system
* @onos.rsModel Groups
*/
@GET
@Produces(MediaType.APPLICATION_JSON)
......@@ -93,14 +97,37 @@ public class GroupsWebResource extends AbstractWebResource {
}
/**
* Returns a group with the given deviceId and appCookie.
*
* @param deviceId device identifier
* @param appCookie group key
* @return a group entry in the system
* @onos.rsModel Group
*/
@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("{deviceId}/{appCookie}")
public Response getGroupByDeviceIdAndAppCookie(@PathParam("deviceId") String deviceId,
@PathParam("appCookie") String appCookie) {
final DeviceId deviceIdInstance = DeviceId.deviceId(deviceId);
final GroupKey appCookieInstance = new DefaultGroupKey(appCookie.getBytes());
Group group = nullIsNotFound(groupService.getGroup(deviceIdInstance, appCookieInstance),
GROUP_NOT_FOUND);
groupsNode.add(codec(Group.class).encode(group, this));
return ok(root).build();
}
/**
* Create new group rule. Creates and installs a new group rule for the
* specified device.
*
* @param deviceId device identifier
* @param stream group rule JSON
* @onos.rsModel GroupsPost
* @return status of the request - CREATED if the JSON is correct,
* BAD_REQUEST if the JSON is invalid
* @onos.rsModel GroupsPost
*/
@POST
@Path("{deviceId}")
......
{
"type": "object",
"title": "group",
"required": [
"id",
"state",
"life",
"packets",
"bytes",
"referenceCount",
"type",
"deviceId",
"appId",
"appCookie",
"buckets"
],
"properties": {
"id": {
"type": "string",
"description": "group id",
"example": "1"
},
"state": {
"type": "string",
"description": "state of the group object",
"example": "PENDING_ADD"
},
"life": {
"type": "integer",
"format": "int64",
"description": "number of milliseconds this group has been alive",
"example": 69889
},
"packets": {
"type": "integer",
"format": "int64",
"description": "number of packets processed by this group",
"example": 22546
},
"bytes": {
"type": "integer",
"format": "int64",
"description": "number of bytes processed by this group",
"example": 1826226
},
"referenceCount": {
"type": "integer",
"format": "int64",
"description": "number of flow rules or other groups reference this group",
"example": 1826226
},
"type": {
"type": "string",
"description": "types of the group",
"example": "ALL"
},
"deviceId": {
"type": "string",
"description": "device identifier",
"example": "of:0000000000000003"
},
"appId": {
"type": "string",
"description": "application identifier",
"example": "1"
},
"appCookie": {
"type": "string",
"description": "application cookie",
"example": "1"
},
"buckets": {
"type": "array",
"xml": {
"name": "buckets",
"wrapped": true
},
"items": {
"type": "object",
"title": "buckets",
"required": [
"treatment",
"weight",
"watchPort",
"watchGroup"
],
"properties": {
"treatment": {
"type": "object",
"title": "treatment",
"required": [
"instructions",
"deferred"
],
"properties": {
"instructions": {
"type": "array",
"title": "treatment",
"required": [
"properties",
"port"
],
"items": {
"type": "object",
"title": "instructions",
"required": [
"type",
"port"
],
"properties": {
"type": {
"type": "string",
"description": "instruction type",
"example": "OUTPUT"
},
"port": {
"type": "string",
"description": "port number",
"example": "2"
}
}
}
}
}
},
"weight": {
"type": "integer",
"format": "int16",
"description": "weight of select group bucket",
"example": "1.0"
},
"watchPort": {
"type": "string",
"description": "port number used for liveness detection for a failover bucket",
"example": "2"
},
"watchGroup": {
"type": "string",
"description": "group identifier used for liveness detection for a failover bucket",
"example": "1"
}
}
}
}
}
}
\ No newline at end of file
......@@ -23,45 +23,65 @@
"referenceCount",
"type",
"deviceId",
"appId",
"appCookie",
"buckets"
],
"properties": {
"id": {
"type": "string",
"description": "group id",
"example": "1"
},
"state": {
"type": "string",
"description": "state of the group object",
"example": "PENDING_ADD"
},
"life": {
"type": "integer",
"format": "int64",
"description": "number of milliseconds this group has been alive",
"example": 69889
},
"packets": {
"type": "integer",
"format": "int64",
"description": "number of packets processed by this group",
"example": 22546
},
"bytes": {
"type": "integer",
"format": "int64",
"description": "number of bytes processed by this group",
"example": 1826226
},
"referenceCount": {
"type": "integer",
"format": "int64",
"description": "number of flow rules or other groups reference this group",
"example": 1826226
},
"type": {
"type": "string",
"description": "types of the group",
"example": "ALL"
},
"deviceId": {
"type": "string",
"description": "device identifier",
"example": "of:0000000000000003"
},
"appId": {
"type": "string",
"description": "application identifier",
"example": "1"
},
"appCookie": {
"type": "string",
"description": "application cookie",
"example": "1"
},
"buckets": {
"type": "array",
"xml": {
......@@ -103,16 +123,34 @@
"properties": {
"type": {
"type": "string",
"description": "instruction type",
"example": "OUTPUT"
},
"port": {
"type": "string",
"description": "port number",
"example": "2"
}
}
}
}
}
},
"weight": {
"type": "integer",
"format": "int16",
"description": "weight of select group bucket",
"example": "1.0"
},
"watchPort": {
"type": "string",
"description": "port number used for liveness detection for a failover bucket",
"example": "2"
},
"watchGroup": {
"type": "string",
"description": "group identifier used for liveness detection for a failover bucket",
"example": "1"
}
}
}
......
......@@ -49,6 +49,7 @@ import org.onosproject.net.group.GroupBuckets;
import org.onosproject.net.group.GroupDescription;
import org.onosproject.net.group.GroupKey;
import org.onosproject.net.group.GroupService;
import org.onosproject.rest.resources.CoreWebApplication;
import javax.ws.rs.core.MediaType;
import java.io.InputStream;
......@@ -70,6 +71,7 @@ import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.onosproject.net.NetTestTools.APP_ID;
/**
......@@ -100,6 +102,10 @@ public class GroupsResourceTest extends ResourceTest {
final MockGroup group5 = new MockGroup(deviceId3, 5, "555", 5);
final MockGroup group6 = new MockGroup(deviceId3, 6, "666", 6);
public GroupsResourceTest() {
super(CoreWebApplication.class);
}
/**
* Mock class for a group.
*/
......@@ -444,6 +450,42 @@ public class GroupsResourceTest extends ResourceTest {
}
/**
* Test the result of a rest api GET with specifying device id and appcookie.
*/
@Test
public void testGroupByDeviceIdAndAppCookie() {
setupMockGroups();
expect(mockGroupService.getGroup(anyObject(), anyObject()))
.andReturn(group5).anyTimes();
replay(mockGroupService);
final WebResource rs = resource();
final String response = rs.path("groups/" + deviceId3 + "/" + "111").get(String.class);
final JsonObject result = JsonObject.readFrom(response);
assertThat(result, notNullValue());
assertThat(result.names(), hasSize(1));
assertThat(result.names().get(0), is("groups"));
final JsonArray jsonFlows = result.get("groups").asArray();
assertThat(jsonFlows, notNullValue());
assertThat(jsonFlows, hasGroup(group5));
}
/**
* Test whether the REST API returns 404 if no entry has been found.
*/
@Test
public void testGroupByDeviceIdAndAppCookieNull() {
setupMockGroups();
expect(mockGroupService.getGroup(anyObject(), anyObject()))
.andReturn(null).anyTimes();
replay(mockGroupService);
final WebResource rs = resource();
final ClientResponse response = rs.path("groups/" + deviceId3 + "/" + "222").get(ClientResponse.class);
assertEquals(404, response.getStatus());
}
/**
* Tests creating a group with POST.
*/
@Test
......