Ray Milkey

Implement REST APIs for flows:

- get all flows
- get all flows for a device
- get all flows for a device with a given ID

Change-Id: Ifb1541e4ae4a7e49f1347b34bef2fe788902368d
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
41 <dependency> 41 <dependency>
42 <groupId>org.easymock</groupId> 42 <groupId>org.easymock</groupId>
43 <artifactId>easymock</artifactId> 43 <artifactId>easymock</artifactId>
44 + <scope>test</scope>
44 </dependency> 45 </dependency>
45 </dependencies> 46 </dependencies>
46 47
......
...@@ -29,6 +29,9 @@ import org.onosproject.net.Host; ...@@ -29,6 +29,9 @@ import org.onosproject.net.Host;
29 import org.onosproject.net.HostLocation; 29 import org.onosproject.net.HostLocation;
30 import org.onosproject.net.Link; 30 import org.onosproject.net.Link;
31 import org.onosproject.net.Port; 31 import org.onosproject.net.Port;
32 +import org.onosproject.net.flow.FlowEntry;
33 +import org.onosproject.net.flow.TrafficSelector;
34 +import org.onosproject.net.flow.TrafficTreatment;
32 import org.onosproject.net.intent.Intent; 35 import org.onosproject.net.intent.Intent;
33 import org.slf4j.Logger; 36 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory; 37 import org.slf4j.LoggerFactory;
...@@ -59,6 +62,9 @@ public class CodecManager implements CodecService { ...@@ -59,6 +62,9 @@ public class CodecManager implements CodecService {
59 registerCodec(Host.class, new HostCodec()); 62 registerCodec(Host.class, new HostCodec());
60 registerCodec(HostLocation.class, new HostLocationCodec()); 63 registerCodec(HostLocation.class, new HostLocationCodec());
61 registerCodec(Intent.class, new IntentCodec()); 64 registerCodec(Intent.class, new IntentCodec());
65 + registerCodec(FlowEntry.class, new FlowEntryCodec());
66 + registerCodec(TrafficTreatment.class, new TrafficTreatmentCodec());
67 + registerCodec(TrafficSelector.class, new TrafficSelectorCodec());
62 log.info("Started"); 68 log.info("Started");
63 } 69 }
64 70
......
1 +/*
2 + * Copyright 2014 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +package org.onosproject.codec.impl;
17 +
18 +import org.onosproject.codec.CodecContext;
19 +import org.onosproject.codec.JsonCodec;
20 +import org.onosproject.net.flow.FlowEntry;
21 +import org.onosproject.net.flow.TrafficSelector;
22 +import org.onosproject.net.flow.TrafficTreatment;
23 +
24 +import com.fasterxml.jackson.databind.node.ObjectNode;
25 +
26 +import static com.google.common.base.Preconditions.checkNotNull;
27 +
28 +/**
29 + * Flow entry JSON codec.
30 + */
31 +public class FlowEntryCodec extends JsonCodec<FlowEntry> {
32 +
33 + @Override
34 + public ObjectNode encode(FlowEntry flowEntry, CodecContext context) {
35 + checkNotNull(flowEntry, "Flow entry cannot be null");
36 +
37 + final ObjectNode result = context.mapper().createObjectNode()
38 + .put("id", Long.toString(flowEntry.id().value()))
39 + .put("appId", flowEntry.appId())
40 + .put("groupId", flowEntry.groupId().id())
41 + .put("priority", flowEntry.priority())
42 + .put("timeout", flowEntry.timeout())
43 + .put("isPermanent", flowEntry.isPermanent())
44 + .put("deviceId", flowEntry.deviceId().toString())
45 + .put("state", flowEntry.state().toString())
46 + .put("life", flowEntry.life())
47 + .put("packets", flowEntry.packets())
48 + .put("bytes", flowEntry.bytes())
49 + .put("lastSeen", flowEntry.lastSeen());
50 +
51 + if (flowEntry.treatment() != null) {
52 + final JsonCodec<TrafficTreatment> treatmentCodec =
53 + new TrafficTreatmentCodec();
54 + result.set("treatment", treatmentCodec.encode(flowEntry.treatment(), context));
55 + }
56 +
57 + if (flowEntry.selector() != null) {
58 + final JsonCodec<TrafficSelector> selectorCodec =
59 + new TrafficSelectorCodec();
60 + result.set("selector", selectorCodec.encode(flowEntry.selector(), context));
61 + }
62 +
63 + return result;
64 + }
65 +
66 +}
67 +
1 +/*
2 + * Copyright 2014 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +package org.onosproject.codec.impl;
17 +
18 +import org.onosproject.codec.CodecContext;
19 +import org.onosproject.codec.JsonCodec;
20 +import org.onosproject.net.flow.TrafficSelector;
21 +import org.onosproject.net.flow.criteria.Criterion;
22 +
23 +import com.fasterxml.jackson.databind.node.ArrayNode;
24 +import com.fasterxml.jackson.databind.node.ObjectNode;
25 +
26 +import static com.google.common.base.Preconditions.checkNotNull;
27 +
28 +/**
29 + * Traffic selector codec.
30 + */
31 +public class TrafficSelectorCodec extends JsonCodec<TrafficSelector> {
32 + @Override
33 + public ObjectNode encode(TrafficSelector selector, CodecContext context) {
34 + checkNotNull(selector, "Traffic selector cannot be null");
35 +
36 + final ObjectNode result = context.mapper().createObjectNode();
37 + final ArrayNode jsonCriteria = result.putArray("criteria");
38 +
39 + if (selector.criteria() != null) {
40 + for (final Criterion criterion :selector.criteria()) {
41 + // TODO: would be better to have a codec that understands criteria
42 + jsonCriteria.add(criterion.toString());
43 + }
44 + }
45 +
46 + return result;
47 + }
48 +}
1 +/*
2 + * Copyright 2014 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +package org.onosproject.codec.impl;
17 +
18 +import org.onosproject.codec.CodecContext;
19 +import org.onosproject.codec.JsonCodec;
20 +import org.onosproject.net.flow.TrafficTreatment;
21 +import org.onosproject.net.flow.instructions.Instruction;
22 +
23 +import com.fasterxml.jackson.databind.node.ArrayNode;
24 +import com.fasterxml.jackson.databind.node.ObjectNode;
25 +
26 +import static com.google.common.base.Preconditions.checkNotNull;
27 +
28 +/**
29 + * Traffic treatment codec.
30 + */
31 +public class TrafficTreatmentCodec extends JsonCodec<TrafficTreatment> {
32 + @Override
33 + public ObjectNode encode(TrafficTreatment treatment, CodecContext context) {
34 + checkNotNull(treatment, "Traffic treatment cannot be null");
35 +
36 + final ObjectNode result = context.mapper().createObjectNode();
37 + final ArrayNode jsonInstructions = result.putArray("instructions");
38 +
39 + if (treatment.instructions() != null) {
40 + for (final Instruction instruction : treatment.instructions()) {
41 + // TODO: would be better to have a codec that understands instructions
42 + jsonInstructions.add(instruction.toString());
43 + }
44 + }
45 +
46 + return result;
47 + }
48 +}
1 +/*
2 + * Copyright 2014 Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +package org.onosproject.rest;
17 +
18 +import javax.ws.rs.GET;
19 +import javax.ws.rs.Path;
20 +import javax.ws.rs.PathParam;
21 +import javax.ws.rs.Produces;
22 +import javax.ws.rs.core.MediaType;
23 +import javax.ws.rs.core.Response;
24 +
25 +import org.onlab.util.ItemNotFoundException;
26 +import org.onosproject.codec.impl.FlowEntryCodec;
27 +import org.onosproject.net.Device;
28 +import org.onosproject.net.DeviceId;
29 +import org.onosproject.net.device.DeviceService;
30 +import org.onosproject.net.flow.FlowEntry;
31 +import org.onosproject.net.flow.FlowRuleService;
32 +
33 +import com.fasterxml.jackson.databind.node.ArrayNode;
34 +import com.fasterxml.jackson.databind.node.ObjectNode;
35 +
36 +/**
37 + * REST resource for interacting with the inventory of flows.
38 + */
39 +
40 +@Path("flows")
41 +public class FlowsWebResource extends AbstractWebResource {
42 + public static final String DEVICE_NOT_FOUND = "Device is not found";
43 +
44 + final FlowRuleService service = get(FlowRuleService.class);
45 + final ObjectNode root = mapper().createObjectNode();
46 + final ArrayNode flowsNode = root.putArray("flows");
47 + final FlowEntryCodec flowEntryCodec = new FlowEntryCodec();
48 +
49 + /**
50 + * Gets an array containing all the intents in the system.
51 + *
52 + * @return array of all the intents in the system
53 + */
54 + @GET
55 + @Produces(MediaType.APPLICATION_JSON)
56 + public Response getFlows() {
57 +
58 + final Iterable<Device> devices = get(DeviceService.class).getDevices();
59 + for (final Device device : devices) {
60 + final Iterable<FlowEntry> deviceEntries = service.getFlowEntries(device.id());
61 + if (deviceEntries != null) {
62 + for (final FlowEntry entry : deviceEntries) {
63 + flowsNode.add(flowEntryCodec.encode(entry, this));
64 + }
65 + }
66 + }
67 +
68 + return ok(root.toString()).build();
69 + }
70 +
71 + /**
72 + * Gets the flows for a device, where the device is specified by Id.
73 + *
74 + * @param deviceId Id of device to look up
75 + * @return flow data as an array
76 + */
77 + @GET
78 + @Produces(MediaType.APPLICATION_JSON)
79 + @Path("{deviceId}")
80 + public Response getFlowByDeviceId(@PathParam("deviceId") String deviceId) {
81 + final Iterable<FlowEntry> deviceEntries =
82 + service.getFlowEntries(DeviceId.deviceId(deviceId));
83 +
84 + if (!deviceEntries.iterator().hasNext()) {
85 + throw new ItemNotFoundException(DEVICE_NOT_FOUND);
86 + }
87 + for (final FlowEntry entry : deviceEntries) {
88 + flowsNode.add(flowEntryCodec.encode(entry, this));
89 + }
90 + return ok(root.toString()).build();
91 + }
92 +
93 + /**
94 + * Gets the flows for a device, where the device is specified by Id.
95 + *
96 + * @param deviceId Id of device to look up
97 + * @param flowId Id of flow to look up
98 + * @return flow data as an array
99 + */
100 + @GET
101 + @Produces(MediaType.APPLICATION_JSON)
102 + @Path("{deviceId}/{flowId}")
103 + public Response getFlowByDeviceIdAndFlowId(@PathParam("deviceId") String deviceId,
104 + @PathParam("flowId") long flowId) {
105 + final Iterable<FlowEntry> deviceEntries =
106 + service.getFlowEntries(DeviceId.deviceId(deviceId));
107 +
108 + if (!deviceEntries.iterator().hasNext()) {
109 + throw new ItemNotFoundException(DEVICE_NOT_FOUND);
110 + }
111 + for (final FlowEntry entry : deviceEntries) {
112 + if (entry.id().value() == flowId) {
113 + flowsNode.add(flowEntryCodec.encode(entry, this));
114 + }
115 + }
116 + return ok(root.toString()).build();
117 + }
118 +}
...@@ -58,7 +58,7 @@ public class IntentsWebResource extends AbstractWebResource { ...@@ -58,7 +58,7 @@ public class IntentsWebResource extends AbstractWebResource {
58 @GET 58 @GET
59 @Produces(MediaType.APPLICATION_JSON) 59 @Produces(MediaType.APPLICATION_JSON)
60 @Path("{id}") 60 @Path("{id}")
61 - public Response getHostById(@PathParam("id") long id) { 61 + public Response getIntentById(@PathParam("id") long id) {
62 final Intent intent = nullIsNotFound(get(IntentService.class) 62 final Intent intent = nullIsNotFound(get(IntentService.class)
63 .getIntent(IntentId.valueOf(id)), 63 .getIntent(IntentId.valueOf(id)),
64 INTENT_NOT_FOUND); 64 INTENT_NOT_FOUND);
......
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
39 org.onosproject.rest.LinksWebResource, 39 org.onosproject.rest.LinksWebResource,
40 org.onosproject.rest.HostsWebResource, 40 org.onosproject.rest.HostsWebResource,
41 org.onosproject.rest.IntentsWebResource, 41 org.onosproject.rest.IntentsWebResource,
42 + org.onosproject.rest.FlowsWebResource,
42 org.onosproject.rest.ConfigResource 43 org.onosproject.rest.ConfigResource
43 </param-value> 44 </param-value>
44 </init-param> 45 </init-param>
......
...@@ -256,6 +256,7 @@ public class IntentsResourceTest extends JerseyTest { ...@@ -256,6 +256,7 @@ public class IntentsResourceTest extends JerseyTest {
256 private static IntentJsonArrayMatcher hasIntent(Intent intent) { 256 private static IntentJsonArrayMatcher hasIntent(Intent intent) {
257 return new IntentJsonArrayMatcher(intent); 257 return new IntentJsonArrayMatcher(intent);
258 } 258 }
259 +
259 @Before 260 @Before
260 public void setUp() { 261 public void setUp() {
261 expect(mockIntentService.getIntents()).andReturn(intents).anyTimes(); 262 expect(mockIntentService.getIntents()).andReturn(intents).anyTimes();
......
...@@ -63,10 +63,7 @@ ...@@ -63,10 +63,7 @@
63 <scope>test</scope> 63 <scope>test</scope>
64 </dependency> 64 </dependency>
65 65
66 - <dependency> 66 +
67 - <groupId>com.google.guava</groupId>
68 - <artifactId>guava</artifactId>
69 - </dependency>
70 67
71 <dependency> 68 <dependency>
72 <groupId>com.sun.jersey</groupId> 69 <groupId>com.sun.jersey</groupId>
...@@ -131,6 +128,7 @@ ...@@ -131,6 +128,7 @@
131 com.fasterxml.jackson.databind, 128 com.fasterxml.jackson.databind,
132 com.fasterxml.jackson.databind.node, 129 com.fasterxml.jackson.databind.node,
133 com.google.common.base.*, 130 com.google.common.base.*,
131 + com.google.common.collect.*,
134 org.eclipse.jetty.websocket.*, 132 org.eclipse.jetty.websocket.*,
135 org.onlab.util.*, 133 org.onlab.util.*,
136 org.onlab.osgi.*, 134 org.onlab.osgi.*,
......