Committed by
Thomas Vachuska
[ONOS-4530] Allow to specify appId when insert FlowRule through REST
- Augment FlowRuleCodec to encode FlowRule - Add unit test for encode method of FlowRuleCodec - Add getFlowByAppId and removeFlowByAppId methods in FlowsWebResource - Add more unit tests for FlowWebResource - Add FlowRules.json swagger doc - Rename Flows.json to FlowEntries.json, correct FlowEntries.json Change-Id: Ic3ec390c13a349e51ae4208adbc478564b6724ba
Showing
6 changed files
with
251 additions
and
44 deletions
| ... | @@ -19,6 +19,7 @@ import com.fasterxml.jackson.databind.JsonNode; | ... | @@ -19,6 +19,7 @@ import com.fasterxml.jackson.databind.JsonNode; |
| 19 | import com.fasterxml.jackson.databind.node.ObjectNode; | 19 | import com.fasterxml.jackson.databind.node.ObjectNode; |
| 20 | import org.onosproject.codec.CodecContext; | 20 | import org.onosproject.codec.CodecContext; |
| 21 | import org.onosproject.codec.JsonCodec; | 21 | import org.onosproject.codec.JsonCodec; |
| 22 | +import org.onosproject.core.ApplicationId; | ||
| 22 | import org.onosproject.core.CoreService; | 23 | import org.onosproject.core.CoreService; |
| 23 | import org.onosproject.net.DeviceId; | 24 | import org.onosproject.net.DeviceId; |
| 24 | import org.onosproject.net.flow.DefaultFlowRule; | 25 | import org.onosproject.net.flow.DefaultFlowRule; |
| ... | @@ -26,6 +27,7 @@ import org.onosproject.net.flow.FlowRule; | ... | @@ -26,6 +27,7 @@ import org.onosproject.net.flow.FlowRule; |
| 26 | import org.onosproject.net.flow.TrafficSelector; | 27 | import org.onosproject.net.flow.TrafficSelector; |
| 27 | import org.onosproject.net.flow.TrafficTreatment; | 28 | import org.onosproject.net.flow.TrafficTreatment; |
| 28 | 29 | ||
| 30 | +import static com.google.common.base.Preconditions.checkNotNull; | ||
| 29 | import static org.onlab.util.Tools.nullIsIllegal; | 31 | import static org.onlab.util.Tools.nullIsIllegal; |
| 30 | 32 | ||
| 31 | /** | 33 | /** |
| ... | @@ -36,6 +38,7 @@ public final class FlowRuleCodec extends JsonCodec<FlowRule> { | ... | @@ -36,6 +38,7 @@ public final class FlowRuleCodec extends JsonCodec<FlowRule> { |
| 36 | private static final String PRIORITY = "priority"; | 38 | private static final String PRIORITY = "priority"; |
| 37 | private static final String TIMEOUT = "timeout"; | 39 | private static final String TIMEOUT = "timeout"; |
| 38 | private static final String IS_PERMANENT = "isPermanent"; | 40 | private static final String IS_PERMANENT = "isPermanent"; |
| 41 | + private static final String APP_ID = "appId"; | ||
| 39 | private static final String TABLE_ID = "tableId"; | 42 | private static final String TABLE_ID = "tableId"; |
| 40 | private static final String DEVICE_ID = "deviceId"; | 43 | private static final String DEVICE_ID = "deviceId"; |
| 41 | private static final String TREATMENT = "treatment"; | 44 | private static final String TREATMENT = "treatment"; |
| ... | @@ -44,6 +47,37 @@ public final class FlowRuleCodec extends JsonCodec<FlowRule> { | ... | @@ -44,6 +47,37 @@ public final class FlowRuleCodec extends JsonCodec<FlowRule> { |
| 44 | " member is required in FlowRule"; | 47 | " member is required in FlowRule"; |
| 45 | public static final String REST_APP_ID = "org.onosproject.rest"; | 48 | public static final String REST_APP_ID = "org.onosproject.rest"; |
| 46 | 49 | ||
| 50 | + @Override | ||
| 51 | + public ObjectNode encode(FlowRule flowRule, CodecContext context) { | ||
| 52 | + checkNotNull(flowRule, "Flow rule cannot be null"); | ||
| 53 | + | ||
| 54 | + CoreService service = context.getService(CoreService.class); | ||
| 55 | + ApplicationId appId = service.getAppId(flowRule.appId()); | ||
| 56 | + String strAppId = (appId == null) ? "<none>" : appId.name(); | ||
| 57 | + | ||
| 58 | + final ObjectNode result = context.mapper().createObjectNode() | ||
| 59 | + .put("id", Long.toString(flowRule.id().value())) | ||
| 60 | + .put("tableId", flowRule.tableId()) | ||
| 61 | + .put("appId", strAppId) | ||
| 62 | + .put("priority", flowRule.priority()) | ||
| 63 | + .put("timeout", flowRule.timeout()) | ||
| 64 | + .put("isPermanent", flowRule.isPermanent()) | ||
| 65 | + .put("deviceId", flowRule.deviceId().toString()); | ||
| 66 | + | ||
| 67 | + if (flowRule.treatment() != null) { | ||
| 68 | + final JsonCodec<TrafficTreatment> treatmentCodec = | ||
| 69 | + context.codec(TrafficTreatment.class); | ||
| 70 | + result.set("treatment", treatmentCodec.encode(flowRule.treatment(), context)); | ||
| 71 | + } | ||
| 72 | + | ||
| 73 | + if (flowRule.selector() != null) { | ||
| 74 | + final JsonCodec<TrafficSelector> selectorCodec = | ||
| 75 | + context.codec(TrafficSelector.class); | ||
| 76 | + result.set("selector", selectorCodec.encode(flowRule.selector(), context)); | ||
| 77 | + } | ||
| 78 | + | ||
| 79 | + return result; | ||
| 80 | + } | ||
| 47 | 81 | ||
| 48 | @Override | 82 | @Override |
| 49 | public FlowRule decode(ObjectNode json, CodecContext context) { | 83 | public FlowRule decode(ObjectNode json, CodecContext context) { |
| ... | @@ -54,8 +88,9 @@ public final class FlowRuleCodec extends JsonCodec<FlowRule> { | ... | @@ -54,8 +88,9 @@ public final class FlowRuleCodec extends JsonCodec<FlowRule> { |
| 54 | FlowRule.Builder resultBuilder = new DefaultFlowRule.Builder(); | 88 | FlowRule.Builder resultBuilder = new DefaultFlowRule.Builder(); |
| 55 | 89 | ||
| 56 | CoreService coreService = context.getService(CoreService.class); | 90 | CoreService coreService = context.getService(CoreService.class); |
| 57 | - resultBuilder.fromApp(coreService | 91 | + JsonNode appIdJson = json.get(APP_ID); |
| 58 | - .registerApplication(REST_APP_ID)); | 92 | + String appId = appIdJson != null ? appIdJson.asText() : REST_APP_ID; |
| 93 | + resultBuilder.fromApp(coreService.registerApplication(appId)); | ||
| 59 | 94 | ||
| 60 | int priority = nullIsIllegal(json.get(PRIORITY), | 95 | int priority = nullIsIllegal(json.get(PRIORITY), |
| 61 | PRIORITY + MISSING_MEMBER_MESSAGE).asInt(); | 96 | PRIORITY + MISSING_MEMBER_MESSAGE).asInt(); | ... | ... |
| ... | @@ -17,6 +17,8 @@ package org.onosproject.codec.impl; | ... | @@ -17,6 +17,8 @@ package org.onosproject.codec.impl; |
| 17 | 17 | ||
| 18 | import com.fasterxml.jackson.databind.JsonNode; | 18 | import com.fasterxml.jackson.databind.JsonNode; |
| 19 | import com.fasterxml.jackson.databind.node.ObjectNode; | 19 | import com.fasterxml.jackson.databind.node.ObjectNode; |
| 20 | +import org.hamcrest.Description; | ||
| 21 | +import org.hamcrest.TypeSafeDiagnosingMatcher; | ||
| 20 | import org.junit.Before; | 22 | import org.junit.Before; |
| 21 | import org.junit.Test; | 23 | import org.junit.Test; |
| 22 | import org.onlab.packet.EthType; | 24 | import org.onlab.packet.EthType; |
| ... | @@ -29,12 +31,14 @@ import org.onlab.packet.VlanId; | ... | @@ -29,12 +31,14 @@ import org.onlab.packet.VlanId; |
| 29 | import org.onosproject.codec.JsonCodec; | 31 | import org.onosproject.codec.JsonCodec; |
| 30 | import org.onosproject.core.CoreService; | 32 | import org.onosproject.core.CoreService; |
| 31 | import org.onosproject.net.ChannelSpacing; | 33 | import org.onosproject.net.ChannelSpacing; |
| 34 | +import org.onosproject.net.DeviceId; | ||
| 32 | import org.onosproject.net.GridType; | 35 | import org.onosproject.net.GridType; |
| 33 | import org.onosproject.net.Lambda; | 36 | import org.onosproject.net.Lambda; |
| 34 | import org.onosproject.net.OchSignal; | 37 | import org.onosproject.net.OchSignal; |
| 35 | import org.onosproject.net.OchSignalType; | 38 | import org.onosproject.net.OchSignalType; |
| 36 | import org.onosproject.net.OduSignalType; | 39 | import org.onosproject.net.OduSignalType; |
| 37 | import org.onosproject.net.PortNumber; | 40 | import org.onosproject.net.PortNumber; |
| 41 | +import org.onosproject.net.flow.DefaultFlowRule; | ||
| 38 | import org.onosproject.net.flow.FlowRule; | 42 | import org.onosproject.net.flow.FlowRule; |
| 39 | import org.onosproject.net.flow.criteria.Criterion; | 43 | import org.onosproject.net.flow.criteria.Criterion; |
| 40 | import org.onosproject.net.flow.criteria.EthCriterion; | 44 | import org.onosproject.net.flow.criteria.EthCriterion; |
| ... | @@ -75,6 +79,7 @@ import java.io.InputStream; | ... | @@ -75,6 +79,7 @@ import java.io.InputStream; |
| 75 | import java.util.SortedMap; | 79 | import java.util.SortedMap; |
| 76 | import java.util.TreeMap; | 80 | import java.util.TreeMap; |
| 77 | 81 | ||
| 82 | +import static org.easymock.EasyMock.anyShort; | ||
| 78 | import static org.easymock.EasyMock.createMock; | 83 | import static org.easymock.EasyMock.createMock; |
| 79 | import static org.easymock.EasyMock.expect; | 84 | import static org.easymock.EasyMock.expect; |
| 80 | import static org.easymock.EasyMock.replay; | 85 | import static org.easymock.EasyMock.replay; |
| ... | @@ -105,6 +110,7 @@ public class FlowRuleCodecTest { | ... | @@ -105,6 +110,7 @@ public class FlowRuleCodecTest { |
| 105 | 110 | ||
| 106 | expect(mockCoreService.registerApplication(FlowRuleCodec.REST_APP_ID)) | 111 | expect(mockCoreService.registerApplication(FlowRuleCodec.REST_APP_ID)) |
| 107 | .andReturn(APP_ID).anyTimes(); | 112 | .andReturn(APP_ID).anyTimes(); |
| 113 | + expect(mockCoreService.getAppId(anyShort())).andReturn(APP_ID).anyTimes(); | ||
| 108 | replay(mockCoreService); | 114 | replay(mockCoreService); |
| 109 | context.registerService(CoreService.class, mockCoreService); | 115 | context.registerService(CoreService.class, mockCoreService); |
| 110 | } | 116 | } |
| ... | @@ -166,6 +172,118 @@ public class FlowRuleCodecTest { | ... | @@ -166,6 +172,118 @@ public class FlowRuleCodecTest { |
| 166 | SortedMap<String, Instruction> instructions = new TreeMap<>(); | 172 | SortedMap<String, Instruction> instructions = new TreeMap<>(); |
| 167 | 173 | ||
| 168 | /** | 174 | /** |
| 175 | + * Checks that a simple rule encodes properly. | ||
| 176 | + */ | ||
| 177 | + @Test | ||
| 178 | + public void testFlowRuleEncode() { | ||
| 179 | + | ||
| 180 | + DeviceId deviceId = DeviceId.deviceId("of:000000000000000a"); | ||
| 181 | + FlowRule permFlowRule = DefaultFlowRule.builder() | ||
| 182 | + .withCookie(1) | ||
| 183 | + .forTable(1) | ||
| 184 | + .withPriority(1) | ||
| 185 | + .makePermanent() | ||
| 186 | + .forDevice(deviceId).build(); | ||
| 187 | + | ||
| 188 | + FlowRule tempFlowRule = DefaultFlowRule.builder() | ||
| 189 | + .withCookie(1) | ||
| 190 | + .forTable(1) | ||
| 191 | + .withPriority(1) | ||
| 192 | + .makeTemporary(1000) | ||
| 193 | + .forDevice(deviceId).build(); | ||
| 194 | + | ||
| 195 | + ObjectNode permFlowRuleJson = flowRuleCodec.encode(permFlowRule, context); | ||
| 196 | + ObjectNode tempFlowRuleJson = flowRuleCodec.encode(tempFlowRule, context); | ||
| 197 | + | ||
| 198 | + assertThat(permFlowRuleJson, FlowRuleJsonMatcher.matchesFlowRule(permFlowRule)); | ||
| 199 | + assertThat(tempFlowRuleJson, FlowRuleJsonMatcher.matchesFlowRule(tempFlowRule)); | ||
| 200 | + } | ||
| 201 | + | ||
| 202 | + private static final class FlowRuleJsonMatcher extends TypeSafeDiagnosingMatcher<JsonNode> { | ||
| 203 | + | ||
| 204 | + private final FlowRule flowRule; | ||
| 205 | + | ||
| 206 | + private FlowRuleJsonMatcher(FlowRule flowRule) { | ||
| 207 | + this.flowRule = flowRule; | ||
| 208 | + } | ||
| 209 | + | ||
| 210 | + @Override | ||
| 211 | + protected boolean matchesSafely(JsonNode jsonNode, Description description) { | ||
| 212 | + | ||
| 213 | + // check id | ||
| 214 | + long jsonId = jsonNode.get("id").asLong(); | ||
| 215 | + long id = flowRule.id().id(); | ||
| 216 | + if (jsonId != id) { | ||
| 217 | + description.appendText("flow rule id was " + jsonId); | ||
| 218 | + return false; | ||
| 219 | + } | ||
| 220 | + | ||
| 221 | + // TODO: need to check application ID | ||
| 222 | + | ||
| 223 | + // check tableId | ||
| 224 | + int jsonTableId = jsonNode.get("tableId").asInt(); | ||
| 225 | + int tableId = flowRule.tableId(); | ||
| 226 | + if (jsonTableId != tableId) { | ||
| 227 | + description.appendText("table id was " + jsonId); | ||
| 228 | + return false; | ||
| 229 | + } | ||
| 230 | + | ||
| 231 | + // check priority | ||
| 232 | + int jsonPriority = jsonNode.get("priority").asInt(); | ||
| 233 | + int priority = flowRule.priority(); | ||
| 234 | + if (jsonPriority != priority) { | ||
| 235 | + description.appendText("priority was " + jsonPriority); | ||
| 236 | + return false; | ||
| 237 | + } | ||
| 238 | + | ||
| 239 | + // check timeout | ||
| 240 | + int jsonTimeout = jsonNode.get("timeout").asInt(); | ||
| 241 | + int timeout = flowRule.timeout(); | ||
| 242 | + if (jsonTimeout != timeout) { | ||
| 243 | + description.appendText("timeout was " + jsonTimeout); | ||
| 244 | + return false; | ||
| 245 | + } | ||
| 246 | + | ||
| 247 | + // check isPermanent | ||
| 248 | + boolean jsonIsPermanent = jsonNode.get("isPermanent").asBoolean(); | ||
| 249 | + boolean isPermanent = flowRule.isPermanent(); | ||
| 250 | + if (jsonIsPermanent != isPermanent) { | ||
| 251 | + description.appendText("isPermanent was " + jsonIsPermanent); | ||
| 252 | + return false; | ||
| 253 | + } | ||
| 254 | + | ||
| 255 | + // check deviceId | ||
| 256 | + String jsonDeviceId = jsonNode.get("deviceId").asText(); | ||
| 257 | + String deviceId = flowRule.deviceId().toString(); | ||
| 258 | + if (!jsonDeviceId.equals(deviceId)) { | ||
| 259 | + description.appendText("deviceId was " + jsonDeviceId); | ||
| 260 | + return false; | ||
| 261 | + } | ||
| 262 | + | ||
| 263 | + // TODO: need to check traffic treatment | ||
| 264 | + | ||
| 265 | + // TODO: need to check selector | ||
| 266 | + | ||
| 267 | + return true; | ||
| 268 | + } | ||
| 269 | + | ||
| 270 | + @Override | ||
| 271 | + public void describeTo(Description description) { | ||
| 272 | + description.appendText(flowRule.toString()); | ||
| 273 | + } | ||
| 274 | + | ||
| 275 | + /** | ||
| 276 | + * Factory to allocate a flow rule matcher. | ||
| 277 | + * | ||
| 278 | + * @param flowRule flow rule object we are looking for | ||
| 279 | + * @return matcher | ||
| 280 | + */ | ||
| 281 | + public static FlowRuleJsonMatcher matchesFlowRule(FlowRule flowRule) { | ||
| 282 | + return new FlowRuleJsonMatcher(flowRule); | ||
| 283 | + } | ||
| 284 | + } | ||
| 285 | + | ||
| 286 | + /** | ||
| 169 | * Looks up an instruction in the instruction map based on type and subtype. | 287 | * Looks up an instruction in the instruction map based on type and subtype. |
| 170 | * | 288 | * |
| 171 | * @param type type string | 289 | * @param type type string | ... | ... |
| ... | @@ -21,6 +21,8 @@ import com.fasterxml.jackson.databind.node.ObjectNode; | ... | @@ -21,6 +21,8 @@ import com.fasterxml.jackson.databind.node.ObjectNode; |
| 21 | import com.google.common.collect.ArrayListMultimap; | 21 | import com.google.common.collect.ArrayListMultimap; |
| 22 | import com.google.common.collect.ListMultimap; | 22 | import com.google.common.collect.ListMultimap; |
| 23 | import org.onlab.util.ItemNotFoundException; | 23 | import org.onlab.util.ItemNotFoundException; |
| 24 | +import org.onosproject.app.ApplicationService; | ||
| 25 | +import org.onosproject.core.ApplicationId; | ||
| 24 | import org.onosproject.net.Device; | 26 | import org.onosproject.net.Device; |
| 25 | import org.onosproject.net.DeviceId; | 27 | import org.onosproject.net.DeviceId; |
| 26 | import org.onosproject.net.device.DeviceService; | 28 | import org.onosproject.net.device.DeviceService; |
| ... | @@ -36,6 +38,7 @@ import javax.ws.rs.POST; | ... | @@ -36,6 +38,7 @@ import javax.ws.rs.POST; |
| 36 | import javax.ws.rs.Path; | 38 | import javax.ws.rs.Path; |
| 37 | import javax.ws.rs.PathParam; | 39 | import javax.ws.rs.PathParam; |
| 38 | import javax.ws.rs.Produces; | 40 | import javax.ws.rs.Produces; |
| 41 | +import javax.ws.rs.QueryParam; | ||
| 39 | import javax.ws.rs.core.Context; | 42 | import javax.ws.rs.core.Context; |
| 40 | import javax.ws.rs.core.MediaType; | 43 | import javax.ws.rs.core.MediaType; |
| 41 | import javax.ws.rs.core.Response; | 44 | import javax.ws.rs.core.Response; |
| ... | @@ -61,6 +64,7 @@ public class FlowsWebResource extends AbstractWebResource { | ... | @@ -61,6 +64,7 @@ public class FlowsWebResource extends AbstractWebResource { |
| 61 | 64 | ||
| 62 | private static final String DEVICE_NOT_FOUND = "Device is not found"; | 65 | private static final String DEVICE_NOT_FOUND = "Device is not found"; |
| 63 | private static final String FLOW_NOT_FOUND = "Flow is not found"; | 66 | private static final String FLOW_NOT_FOUND = "Flow is not found"; |
| 67 | + private static final String APP_ID_NOT_FOUND = "Application Id is not found"; | ||
| 64 | private static final String FLOWS = "flows"; | 68 | private static final String FLOWS = "flows"; |
| 65 | private static final String DEVICE_ID = "deviceId"; | 69 | private static final String DEVICE_ID = "deviceId"; |
| 66 | private static final String FLOW_ID = "flowId"; | 70 | private static final String FLOW_ID = "flowId"; |
| ... | @@ -73,7 +77,7 @@ public class FlowsWebResource extends AbstractWebResource { | ... | @@ -73,7 +77,7 @@ public class FlowsWebResource extends AbstractWebResource { |
| 73 | * Gets all flow entries. Returns array of all flow rules in the system. | 77 | * Gets all flow entries. Returns array of all flow rules in the system. |
| 74 | * | 78 | * |
| 75 | * @return 200 OK with a collection of flows | 79 | * @return 200 OK with a collection of flows |
| 76 | - * @onos.rsModel Flows | 80 | + * @onos.rsModel FlowEntries |
| 77 | */ | 81 | */ |
| 78 | @GET | 82 | @GET |
| 79 | @Produces(MediaType.APPLICATION_JSON) | 83 | @Produces(MediaType.APPLICATION_JSON) |
| ... | @@ -107,10 +111,15 @@ public class FlowsWebResource extends AbstractWebResource { | ... | @@ -107,10 +111,15 @@ public class FlowsWebResource extends AbstractWebResource { |
| 107 | @POST | 111 | @POST |
| 108 | @Consumes(MediaType.APPLICATION_JSON) | 112 | @Consumes(MediaType.APPLICATION_JSON) |
| 109 | @Produces(MediaType.APPLICATION_JSON) | 113 | @Produces(MediaType.APPLICATION_JSON) |
| 110 | - public Response createFlows(InputStream stream) { | 114 | + public Response createFlows(@QueryParam("appId") String appId, InputStream stream) { |
| 111 | try { | 115 | try { |
| 112 | ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream); | 116 | ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream); |
| 113 | ArrayNode flowsArray = (ArrayNode) jsonTree.get(FLOWS); | 117 | ArrayNode flowsArray = (ArrayNode) jsonTree.get(FLOWS); |
| 118 | + | ||
| 119 | + if (appId != null) { | ||
| 120 | + flowsArray.forEach(flowJson -> ((ObjectNode) flowJson).put("appId", appId)); | ||
| 121 | + } | ||
| 122 | + | ||
| 114 | List<FlowRule> rules = codec(FlowRule.class).decode(flowsArray, this); | 123 | List<FlowRule> rules = codec(FlowRule.class).decode(flowsArray, this); |
| 115 | service.applyFlowRules(rules.toArray(new FlowRule[rules.size()])); | 124 | service.applyFlowRules(rules.toArray(new FlowRule[rules.size()])); |
| 116 | rules.forEach(flowRule -> { | 125 | rules.forEach(flowRule -> { |
| ... | @@ -131,10 +140,11 @@ public class FlowsWebResource extends AbstractWebResource { | ... | @@ -131,10 +140,11 @@ public class FlowsWebResource extends AbstractWebResource { |
| 131 | * | 140 | * |
| 132 | * @param deviceId device identifier | 141 | * @param deviceId device identifier |
| 133 | * @return 200 OK with a collection of flows of given device | 142 | * @return 200 OK with a collection of flows of given device |
| 134 | - * @onos.rsModel Flows | 143 | + * @onos.rsModel FlowEntries |
| 135 | */ | 144 | */ |
| 136 | @GET | 145 | @GET |
| 137 | @Produces(MediaType.APPLICATION_JSON) | 146 | @Produces(MediaType.APPLICATION_JSON) |
| 147 | + // TODO: we need to add "/device" suffix to the path to differentiate with appId | ||
| 138 | @Path("{deviceId}") | 148 | @Path("{deviceId}") |
| 139 | public Response getFlowByDeviceId(@PathParam("deviceId") String deviceId) { | 149 | public Response getFlowByDeviceId(@PathParam("deviceId") String deviceId) { |
| 140 | final Iterable<FlowEntry> flowEntries = | 150 | final Iterable<FlowEntry> flowEntries = |
| ... | @@ -150,13 +160,13 @@ public class FlowsWebResource extends AbstractWebResource { | ... | @@ -150,13 +160,13 @@ public class FlowsWebResource extends AbstractWebResource { |
| 150 | } | 160 | } |
| 151 | 161 | ||
| 152 | /** | 162 | /** |
| 153 | - * Gets flow rule. Returns the flow entry specified by the device id and | 163 | + * Gets flow rules. Returns the flow entry specified by the device id and |
| 154 | * flow rule id. | 164 | * flow rule id. |
| 155 | * | 165 | * |
| 156 | * @param deviceId device identifier | 166 | * @param deviceId device identifier |
| 157 | * @param flowId flow rule identifier | 167 | * @param flowId flow rule identifier |
| 158 | - * @return 200 OK with a flows of given device and flow | 168 | + * @return 200 OK with a collection of flows of given device and flow |
| 159 | - * @onos.rsModel Flows | 169 | + * @onos.rsModel FlowEntries |
| 160 | */ | 170 | */ |
| 161 | @GET | 171 | @GET |
| 162 | @Produces(MediaType.APPLICATION_JSON) | 172 | @Produces(MediaType.APPLICATION_JSON) |
| ... | @@ -178,6 +188,43 @@ public class FlowsWebResource extends AbstractWebResource { | ... | @@ -178,6 +188,43 @@ public class FlowsWebResource extends AbstractWebResource { |
| 178 | } | 188 | } |
| 179 | 189 | ||
| 180 | /** | 190 | /** |
| 191 | + * Gets flow rules generated by an application. | ||
| 192 | + * Returns the flow rule specified by the application id. | ||
| 193 | + * | ||
| 194 | + * @param appId application identifier | ||
| 195 | + * @return 200 OK with a collection of flows of given application id | ||
| 196 | + * @onos.rsModel FlowRules | ||
| 197 | + */ | ||
| 198 | + @GET | ||
| 199 | + @Produces(MediaType.APPLICATION_JSON) | ||
| 200 | + @Path("application/{appId}") | ||
| 201 | + public Response getFlowByAppId(@PathParam("appId") String appId) { | ||
| 202 | + final ApplicationService appService = get(ApplicationService.class); | ||
| 203 | + final ApplicationId idInstant = nullIsNotFound(appService.getId(appId), APP_ID_NOT_FOUND); | ||
| 204 | + final Iterable<FlowRule> flowRules = service.getFlowRulesById(idInstant); | ||
| 205 | + | ||
| 206 | + flowRules.forEach(flow -> flowsNode.add(codec(FlowRule.class).encode(flow, this))); | ||
| 207 | + return ok(root).build(); | ||
| 208 | + } | ||
| 209 | + | ||
| 210 | + /** | ||
| 211 | + * Removes flow rules by application ID. | ||
| 212 | + * Removes a collection of flow rules generated by the given application. | ||
| 213 | + * | ||
| 214 | + * @param appId application identifier | ||
| 215 | + * @return 204 NO CONTENT | ||
| 216 | + */ | ||
| 217 | + @DELETE | ||
| 218 | + @Produces(MediaType.APPLICATION_JSON) | ||
| 219 | + @Path("application/{appId}") | ||
| 220 | + public Response removeFlowByAppId(@PathParam("appId") String appId) { | ||
| 221 | + final ApplicationService appService = get(ApplicationService.class); | ||
| 222 | + final ApplicationId idInstant = nullIsNotFound(appService.getId(appId), APP_ID_NOT_FOUND); | ||
| 223 | + service.removeFlowRulesById(idInstant); | ||
| 224 | + return Response.noContent().build(); | ||
| 225 | + } | ||
| 226 | + | ||
| 227 | + /** | ||
| 181 | * Creates new flow rule. Creates and installs a new flow rule for the | 228 | * Creates new flow rule. Creates and installs a new flow rule for the |
| 182 | * specified device. <br> | 229 | * specified device. <br> |
| 183 | * Instructions description: | 230 | * Instructions description: |
| ... | @@ -187,6 +234,7 @@ public class FlowsWebResource extends AbstractWebResource { | ... | @@ -187,6 +234,7 @@ public class FlowsWebResource extends AbstractWebResource { |
| 187 | * https://wiki.onosproject.org/display/ONOS/Flow+Rule+Criteria | 234 | * https://wiki.onosproject.org/display/ONOS/Flow+Rule+Criteria |
| 188 | * | 235 | * |
| 189 | * @param deviceId device identifier | 236 | * @param deviceId device identifier |
| 237 | + * @param appId application identifier | ||
| 190 | * @param stream flow rule JSON | 238 | * @param stream flow rule JSON |
| 191 | * @return status of the request - CREATED if the JSON is correct, | 239 | * @return status of the request - CREATED if the JSON is correct, |
| 192 | * BAD_REQUEST if the JSON is invalid | 240 | * BAD_REQUEST if the JSON is invalid |
| ... | @@ -197,6 +245,7 @@ public class FlowsWebResource extends AbstractWebResource { | ... | @@ -197,6 +245,7 @@ public class FlowsWebResource extends AbstractWebResource { |
| 197 | @Consumes(MediaType.APPLICATION_JSON) | 245 | @Consumes(MediaType.APPLICATION_JSON) |
| 198 | @Produces(MediaType.APPLICATION_JSON) | 246 | @Produces(MediaType.APPLICATION_JSON) |
| 199 | public Response createFlow(@PathParam("deviceId") String deviceId, | 247 | public Response createFlow(@PathParam("deviceId") String deviceId, |
| 248 | + @QueryParam("appId") String appId, | ||
| 200 | InputStream stream) { | 249 | InputStream stream) { |
| 201 | try { | 250 | try { |
| 202 | ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream); | 251 | ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream); |
| ... | @@ -207,6 +256,11 @@ public class FlowsWebResource extends AbstractWebResource { | ... | @@ -207,6 +256,11 @@ public class FlowsWebResource extends AbstractWebResource { |
| 207 | "Invalid deviceId in flow creation request"); | 256 | "Invalid deviceId in flow creation request"); |
| 208 | } | 257 | } |
| 209 | jsonTree.put("deviceId", deviceId); | 258 | jsonTree.put("deviceId", deviceId); |
| 259 | + | ||
| 260 | + if (appId != null) { | ||
| 261 | + jsonTree.put("appId", appId); | ||
| 262 | + } | ||
| 263 | + | ||
| 210 | FlowRule rule = codec(FlowRule.class).decode(jsonTree, this); | 264 | FlowRule rule = codec(FlowRule.class).decode(jsonTree, this); |
| 211 | service.applyFlowRules(rule); | 265 | service.applyFlowRules(rule); |
| 212 | UriBuilder locationBuilder = uriInfo.getBaseUriBuilder() | 266 | UriBuilder locationBuilder = uriInfo.getBaseUriBuilder() |
| ... | @@ -223,7 +277,7 @@ public class FlowsWebResource extends AbstractWebResource { | ... | @@ -223,7 +277,7 @@ public class FlowsWebResource extends AbstractWebResource { |
| 223 | } | 277 | } |
| 224 | 278 | ||
| 225 | /** | 279 | /** |
| 226 | - * Remove flow rule. Removes the specified flow rule. | 280 | + * Removes flow rule. Removes the specified flow rule. |
| 227 | * | 281 | * |
| 228 | * @param deviceId device identifier | 282 | * @param deviceId device identifier |
| 229 | * @param flowId flow rule identifier | 283 | * @param flowId flow rule identifier | ... | ... |
| ... | @@ -135,9 +135,6 @@ | ... | @@ -135,9 +135,6 @@ |
| 135 | } | 135 | } |
| 136 | } | 136 | } |
| 137 | } | 137 | } |
| 138 | - } | ||
| 139 | - } | ||
| 140 | - } | ||
| 141 | }, | 138 | }, |
| 142 | "selector": { | 139 | "selector": { |
| 143 | "type": "object", | 140 | "type": "object", |
| ... | @@ -158,14 +155,14 @@ | ... | @@ -158,14 +155,14 @@ |
| 158 | "properties": { | 155 | "properties": { |
| 159 | "type": { | 156 | "type": { |
| 160 | "type": "string", | 157 | "type": "string", |
| 161 | - "description":"Ethernet field name", | 158 | + "description": "Ethernet field name", |
| 162 | "example": "ETH_TYPE" | 159 | "example": "ETH_TYPE" |
| 163 | }, | 160 | }, |
| 164 | "ethType": { | 161 | "ethType": { |
| 165 | "type": "int64", | 162 | "type": "int64", |
| 166 | "format": "int64", | 163 | "format": "int64", |
| 167 | "example": "0x88cc", | 164 | "example": "0x88cc", |
| 168 | - "description":"Ethernet frame type" | 165 | + "description": "Ethernet frame type" |
| 169 | }, | 166 | }, |
| 170 | "mac": { | 167 | "mac": { |
| 171 | "type": "string", | 168 | "type": "string", |
| ... | @@ -175,13 +172,13 @@ | ... | @@ -175,13 +172,13 @@ |
| 175 | "type": "int64", | 172 | "type": "int64", |
| 176 | "format": "int64", | 173 | "format": "int64", |
| 177 | "example": 1, | 174 | "example": 1, |
| 178 | - "description":"Match port" | 175 | + "description": "Match port" |
| 179 | }, | 176 | }, |
| 180 | "metadata": { | 177 | "metadata": { |
| 181 | "type": "Hex16", | 178 | "type": "Hex16", |
| 182 | "format": "Hex16", | 179 | "format": "Hex16", |
| 183 | "example": "0xabcdL", | 180 | "example": "0xabcdL", |
| 184 | - "description":"Metadata passed between tables" | 181 | + "description": "Metadata passed between tables" |
| 185 | }, | 182 | }, |
| 186 | "vlanId": { | 183 | "vlanId": { |
| 187 | "type": "uint16", | 184 | "type": "uint16", |
| ... | @@ -192,116 +189,116 @@ | ... | @@ -192,116 +189,116 @@ |
| 192 | "type": "int64", | 189 | "type": "int64", |
| 193 | "format": "int64", | 190 | "format": "int64", |
| 194 | "example": 1, | 191 | "example": 1, |
| 195 | - "description":"VLAN priority." | 192 | + "description": "VLAN priority." |
| 196 | }, | 193 | }, |
| 197 | "ipDscp": { | 194 | "ipDscp": { |
| 198 | "type": "byte", | 195 | "type": "byte", |
| 199 | "format": "byte", | 196 | "format": "byte", |
| 200 | - "description":"IP DSCP (6 bits in ToS field)" | 197 | + "description": "IP DSCP (6 bits in ToS field)" |
| 201 | }, | 198 | }, |
| 202 | "ipEcn": { | 199 | "ipEcn": { |
| 203 | "type": "byte", | 200 | "type": "byte", |
| 204 | "format": "byte", | 201 | "format": "byte", |
| 205 | - "description":"IP ECN (2 bits in ToS field)." | 202 | + "description": "IP ECN (2 bits in ToS field)." |
| 206 | }, | 203 | }, |
| 207 | "protocol": { | 204 | "protocol": { |
| 208 | "type": "uint16", | 205 | "type": "uint16", |
| 209 | "format": "uint16", | 206 | "format": "uint16", |
| 210 | "example": 1, | 207 | "example": 1, |
| 211 | - "description":"IP protocol" | 208 | + "description": "IP protocol" |
| 212 | }, | 209 | }, |
| 213 | "ip": { | 210 | "ip": { |
| 214 | "type": "string", | 211 | "type": "string", |
| 215 | "example": "10.1.1.0/24", | 212 | "example": "10.1.1.0/24", |
| 216 | - "description":"IP source address" | 213 | + "description": "IP source address" |
| 217 | }, | 214 | }, |
| 218 | "tcpPort": { | 215 | "tcpPort": { |
| 219 | "type": "integer", | 216 | "type": "integer", |
| 220 | "format": "uint16", | 217 | "format": "uint16", |
| 221 | "example": 1, | 218 | "example": 1, |
| 222 | - "description":"TCP source address" | 219 | + "description": "TCP source address" |
| 223 | }, | 220 | }, |
| 224 | "udpPort": { | 221 | "udpPort": { |
| 225 | "type": "uint16", | 222 | "type": "uint16", |
| 226 | "format": "uint16", | 223 | "format": "uint16", |
| 227 | "example": 1, | 224 | "example": 1, |
| 228 | - "description":"UDP source address" | 225 | + "description": "UDP source address" |
| 229 | }, | 226 | }, |
| 230 | "sctpPort": { | 227 | "sctpPort": { |
| 231 | "type": "uint16", | 228 | "type": "uint16", |
| 232 | "format": "uint16", | 229 | "format": "uint16", |
| 233 | "example": 1, | 230 | "example": 1, |
| 234 | - "description":"SCTP source address" | 231 | + "description": "SCTP source address" |
| 235 | }, | 232 | }, |
| 236 | "icmpType": { | 233 | "icmpType": { |
| 237 | "type": "uint16", | 234 | "type": "uint16", |
| 238 | "format": "uint16", | 235 | "format": "uint16", |
| 239 | "example": 1, | 236 | "example": 1, |
| 240 | - "description":"Internet Control Message Protocol for IPV4 code (RFC0792)" | 237 | + "description": "Internet Control Message Protocol for IPV4 code (RFC0792)" |
| 241 | }, | 238 | }, |
| 242 | "icmpCode": { | 239 | "icmpCode": { |
| 243 | "type": "uint16", | 240 | "type": "uint16", |
| 244 | "format": "uint16", | 241 | "format": "uint16", |
| 245 | "example": 1, | 242 | "example": 1, |
| 246 | - "description":"Internet Control Message Protocol for IPV4 code (RFC0792)" | 243 | + "description": "Internet Control Message Protocol for IPV4 code (RFC0792)" |
| 247 | }, | 244 | }, |
| 248 | "flowLabel": { | 245 | "flowLabel": { |
| 249 | "type": "Hex16", | 246 | "type": "Hex16", |
| 250 | "format": "Hex16", | 247 | "format": "Hex16", |
| 251 | "example": "0xffffe", | 248 | "example": "0xffffe", |
| 252 | - "description":"IPv6 Flow Label (RFC 6437)" | 249 | + "description": "IPv6 Flow Label (RFC 6437)" |
| 253 | }, | 250 | }, |
| 254 | "icmpv6Type": { | 251 | "icmpv6Type": { |
| 255 | "type": "uint16", | 252 | "type": "uint16", |
| 256 | "format": "uint16", | 253 | "format": "uint16", |
| 257 | "example": 1, | 254 | "example": 1, |
| 258 | - "description":"Internet Control Message Protocol for IPV6 type (RFC2463)" | 255 | + "description": "Internet Control Message Protocol for IPV6 type (RFC2463)" |
| 259 | }, | 256 | }, |
| 260 | "icmpv6Code": { | 257 | "icmpv6Code": { |
| 261 | "type": "uint16", | 258 | "type": "uint16", |
| 262 | "format": "uint16", | 259 | "format": "uint16", |
| 263 | "example": 1, | 260 | "example": 1, |
| 264 | - "description":"Internet Control Message Protocol for IPV6 code (RFC2463)" | 261 | + "description": "Internet Control Message Protocol for IPV6 code (RFC2463)" |
| 265 | }, | 262 | }, |
| 266 | "targetAddress": { | 263 | "targetAddress": { |
| 267 | "type": "String", | 264 | "type": "String", |
| 268 | "example": "10.1.1.0/24", | 265 | "example": "10.1.1.0/24", |
| 269 | - "description":"IPv6 Neighbor discovery target address" | 266 | + "description": "IPv6 Neighbor discovery target address" |
| 270 | }, | 267 | }, |
| 271 | "label": { | 268 | "label": { |
| 272 | "type": "int32", | 269 | "type": "int32", |
| 273 | "format": "int32", | 270 | "format": "int32", |
| 274 | "example": 1, | 271 | "example": 1, |
| 275 | - "description":"MPLS label" | 272 | + "description": "MPLS label" |
| 276 | }, | 273 | }, |
| 277 | "exthdrFlags": { | 274 | "exthdrFlags": { |
| 278 | "type": "int64", | 275 | "type": "int64", |
| 279 | "format": "int64", | 276 | "format": "int64", |
| 280 | "example": 1, | 277 | "example": 1, |
| 281 | - "description":"IPv6 extension header pseudo-field" | 278 | + "description": "IPv6 extension header pseudo-field" |
| 282 | }, | 279 | }, |
| 283 | "lambda": { | 280 | "lambda": { |
| 284 | "type": "int64", | 281 | "type": "int64", |
| 285 | "format": "int64", | 282 | "format": "int64", |
| 286 | "example": 1, | 283 | "example": 1, |
| 287 | - "description":"wavelength abstraction" | 284 | + "description": "wavelength abstraction" |
| 288 | }, | 285 | }, |
| 289 | "gridType": { | 286 | "gridType": { |
| 290 | "type": "String", | 287 | "type": "String", |
| 291 | "example": "DWDM", | 288 | "example": "DWDM", |
| 292 | - "description":"Type of wavelength grid" | 289 | + "description": "Type of wavelength grid" |
| 293 | }, | 290 | }, |
| 294 | "channelSpacing": { | 291 | "channelSpacing": { |
| 295 | "type": "int64", | 292 | "type": "int64", |
| 296 | "format": "int64", | 293 | "format": "int64", |
| 297 | "example": 100, | 294 | "example": 100, |
| 298 | - "description":"Optical channel spacing" | 295 | + "description": "Optical channel spacing" |
| 299 | }, | 296 | }, |
| 300 | "spacingMultiplier": { | 297 | "spacingMultiplier": { |
| 301 | "type": "integer", | 298 | "type": "integer", |
| 302 | "format": "int64", | 299 | "format": "int64", |
| 303 | "example": 4, | 300 | "example": 4, |
| 304 | - "description":"Optical channel spacing multiplier" | 301 | + "description": "Optical channel spacing multiplier" |
| 305 | }, | 302 | }, |
| 306 | "slotGranularity": { | 303 | "slotGranularity": { |
| 307 | "type": "int64", | 304 | "type": "int64", |
| ... | @@ -312,42 +309,42 @@ | ... | @@ -312,42 +309,42 @@ |
| 312 | "type": "integer", | 309 | "type": "integer", |
| 313 | "format": "int64", | 310 | "format": "int64", |
| 314 | "example": 1, | 311 | "example": 1, |
| 315 | - "description":"Optical channel signal ID" | 312 | + "description": "Optical channel signal ID" |
| 316 | }, | 313 | }, |
| 317 | "tunnelId": { | 314 | "tunnelId": { |
| 318 | "type": "int64", | 315 | "type": "int64", |
| 319 | "format": "int64", | 316 | "format": "int64", |
| 320 | "example": 5, | 317 | "example": 5, |
| 321 | - "description":"Tunnel ID" | 318 | + "description": "Tunnel ID" |
| 322 | }, | 319 | }, |
| 323 | "ochSignalType": { | 320 | "ochSignalType": { |
| 324 | "type": "int64", | 321 | "type": "int64", |
| 325 | "format": "int64", | 322 | "format": "int64", |
| 326 | "example": 1, | 323 | "example": 1, |
| 327 | - "description":"Optical channel signal type" | 324 | + "description": "Optical channel signal type" |
| 328 | }, | 325 | }, |
| 329 | "oduSignalId": { | 326 | "oduSignalId": { |
| 330 | "type": "int64", | 327 | "type": "int64", |
| 331 | "format": "int64", | 328 | "format": "int64", |
| 332 | "example": 1, | 329 | "example": 1, |
| 333 | - "description":"ODU (Optical channel Data Unit) signal ID." | 330 | + "description": "ODU (Optical channel Data Unit) signal ID." |
| 334 | }, | 331 | }, |
| 335 | "tributaryPortNumber": { | 332 | "tributaryPortNumber": { |
| 336 | "type": "int64", | 333 | "type": "int64", |
| 337 | "format": "int64", | 334 | "format": "int64", |
| 338 | "example": 11, | 335 | "example": 11, |
| 339 | - "description":"OPU (Optical channel Payload Unit) port number." | 336 | + "description": "OPU (Optical channel Payload Unit) port number." |
| 340 | }, | 337 | }, |
| 341 | "tributarySlotLen": { | 338 | "tributarySlotLen": { |
| 342 | "type": "int64", | 339 | "type": "int64", |
| 343 | "format": "int64", | 340 | "format": "int64", |
| 344 | "example": 80, | 341 | "example": 80, |
| 345 | - "description":"OPU (Optical channel Payload Unit) slot length." | 342 | + "description": "OPU (Optical channel Payload Unit) slot length." |
| 346 | }, | 343 | }, |
| 347 | "tributarySlotBitmap": { | 344 | "tributarySlotBitmap": { |
| 348 | "type": "array", | 345 | "type": "array", |
| 349 | "title": "tributarySlotBitmap", | 346 | "title": "tributarySlotBitmap", |
| 350 | - "description":"OPU (Optical channel Payload Unit) slot bitmap.", | 347 | + "description": "OPU (Optical channel Payload Unit) slot bitmap.", |
| 351 | "required": [ | 348 | "required": [ |
| 352 | "byte", | 349 | "byte", |
| 353 | "port" | 350 | "port" |
| ... | @@ -362,7 +359,10 @@ | ... | @@ -362,7 +359,10 @@ |
| 362 | "type": "int64", | 359 | "type": "int64", |
| 363 | "format": "int64", | 360 | "format": "int64", |
| 364 | "example": 4, | 361 | "example": 4, |
| 365 | - "description":"ODU (Optical channel Data Unit) signal type." | 362 | + "description": "ODU (Optical channel Data Unit) signal type." |
| 363 | + } | ||
| 364 | + } | ||
| 365 | + } | ||
| 366 | } | 366 | } |
| 367 | } | 367 | } |
| 368 | } | 368 | } | ... | ... |
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
-
Please register or login to post a comment