Prince Pereira
Committed by Gerrit Code Review

Fix for ONOS-4834. Created rest api for removing the flows using appid, device id and flowid.

Change-Id: I7389fa017287f0daac299229914e7fbf9c60a91e
...@@ -301,6 +301,35 @@ public class FlowsWebResource extends AbstractWebResource { ...@@ -301,6 +301,35 @@ public class FlowsWebResource extends AbstractWebResource {
301 } 301 }
302 302
303 /** 303 /**
304 + * Removes the specified flow rule based on application ID, device ID and flow ID.
305 + *
306 + * @param appId app identifier
307 + * @param deviceId device identifier
308 + * @param flowId flow rule identifier
309 + * @return 204 NO CONTENT
310 + */
311 + @DELETE
312 + @Path("{appId}/{deviceId}/{flowId}")
313 + public Response deleteFlowByAppIdDeviceIdAndFlowId(@PathParam("appId") String appId,
314 + @PathParam("deviceId") String deviceId,
315 + @PathParam("flowId") long flowId) {
316 + final ApplicationService appService = get(ApplicationService.class);
317 + final ApplicationId idInstant = nullIsNotFound(appService.getId(appId), APP_ID_NOT_FOUND);
318 +
319 + final Iterable<FlowEntry> flowEntries =
320 + service.getFlowEntries(DeviceId.deviceId(deviceId));
321 +
322 + if (!flowEntries.iterator().hasNext()) {
323 + throw new ItemNotFoundException(DEVICE_NOT_FOUND);
324 + }
325 +
326 + StreamSupport.stream(flowEntries.spliterator(), false)
327 + .filter(entry -> (entry.id().value() == flowId) && (entry.appId() == idInstant.id()))
328 + .forEach(service::removeFlowRules);
329 + return Response.noContent().build();
330 + }
331 +
332 + /**
304 * Removes a batch of flow rules. 333 * Removes a batch of flow rules.
305 * 334 *
306 * @param stream stream for posted JSON 335 * @param stream stream for posted JSON
...@@ -343,4 +372,52 @@ public class FlowsWebResource extends AbstractWebResource { ...@@ -343,4 +372,52 @@ public class FlowsWebResource extends AbstractWebResource {
343 service.removeFlowRules(rulesToRemove.toArray(new FlowEntry[0])); 372 service.removeFlowRules(rulesToRemove.toArray(new FlowEntry[0]));
344 return Response.noContent().build(); 373 return Response.noContent().build();
345 } 374 }
375 +
376 + /**
377 + * Removes collection of flow rules generated by the given application.
378 + *
379 + * @param appId app identifier
380 + * @param stream stream for posted JSON
381 + * @return 204 NO CONTENT
382 + */
383 + @DELETE
384 + @Path("{appId}")
385 + public Response deleteFlowsByAppId(@PathParam("appId") String appId, InputStream stream) {
386 + final ApplicationService appService = get(ApplicationService.class);
387 + final ApplicationId idInstant = nullIsNotFound(appService.getId(appId), APP_ID_NOT_FOUND);
388 + ListMultimap<DeviceId, Long> deviceMap = ArrayListMultimap.create();
389 + List<FlowEntry> rulesToRemove = new ArrayList<>();
390 +
391 + try {
392 + ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
393 +
394 + JsonNode jsonFlows = jsonTree.get("flows");
395 +
396 + jsonFlows.forEach(node -> {
397 + DeviceId deviceId =
398 + DeviceId.deviceId(
399 + nullIsNotFound(node.get(DEVICE_ID),
400 + DEVICE_NOT_FOUND).asText());
401 + long flowId = nullIsNotFound(node.get(FLOW_ID),
402 + FLOW_NOT_FOUND).asLong();
403 + deviceMap.put(deviceId, flowId);
404 +
405 + });
406 + } catch (IOException ex) {
407 + throw new IllegalArgumentException(ex);
408 + }
409 +
410 + deviceMap.keySet().forEach(deviceId -> {
411 + List<Long> flowIds = deviceMap.get(deviceId);
412 + Iterable<FlowEntry> entries = service.getFlowEntries(deviceId);
413 + flowIds.forEach(flowId -> {
414 + StreamSupport.stream(entries.spliterator(), false)
415 + .filter(entry -> (entry.id().value() == flowId) && (entry.appId() == idInstant.id()))
416 + .forEach(rulesToRemove::add);
417 + });
418 + });
419 +
420 + service.removeFlowRules(rulesToRemove.toArray(new FlowEntry[0]));
421 + return Response.noContent().build();
422 + }
346 } 423 }
......
...@@ -63,6 +63,7 @@ import java.io.InputStream; ...@@ -63,6 +63,7 @@ import java.io.InputStream;
63 import java.net.HttpURLConnection; 63 import java.net.HttpURLConnection;
64 import java.util.HashMap; 64 import java.util.HashMap;
65 import java.util.HashSet; 65 import java.util.HashSet;
66 +import java.util.Objects;
66 import java.util.Set; 67 import java.util.Set;
67 68
68 import static org.easymock.EasyMock.anyObject; 69 import static org.easymock.EasyMock.anyObject;
...@@ -182,7 +183,7 @@ public class FlowsResourceTest extends ResourceTest { ...@@ -182,7 +183,7 @@ public class FlowsResourceTest extends ResourceTest {
182 183
183 @Override 184 @Override
184 public short appId() { 185 public short appId() {
185 - return 2; 186 + return (short) Objects.hash("foo");
186 } 187 }
187 188
188 @Override 189 @Override
...@@ -961,4 +962,28 @@ public class FlowsResourceTest extends ResourceTest { ...@@ -961,4 +962,28 @@ public class FlowsResourceTest extends ResourceTest {
961 assertThat(deleteResponse.getStatus(), 962 assertThat(deleteResponse.getStatus(),
962 is(HttpURLConnection.HTTP_NO_CONTENT)); 963 is(HttpURLConnection.HTTP_NO_CONTENT));
963 } 964 }
965 +
966 + /**
967 + * Tests the result of a rest api DELETE for application Id, device id and flow id.
968 + */
969 + @Test
970 + public void testRemoveFlowByAppIdDeviceIdAndFlowId() {
971 + setupMockFlows();
972 + expect(mockApplicationService.getId(anyObject())).andReturn(APP_ID).anyTimes();
973 + replay(mockApplicationService);
974 + mockFlowService.removeFlowRules(anyObject());
975 + expectLastCall();
976 + replay(mockFlowService);
977 +
978 + WebTarget wt = target();
979 +
980 + String location = "/flows/4/1/155";
981 +
982 + Response deleteResponse = wt.path(location)
983 + .request(MediaType.APPLICATION_JSON_TYPE)
984 + .delete();
985 + assertThat(deleteResponse.getStatus(),
986 + is(HttpURLConnection.HTTP_NO_CONTENT));
987 + }
988 +
964 } 989 }
......