Ray Milkey

Add bulk delete for flows

Change-Id: I77f266c75d0f9d1e99155eb48c216bff3fab2f40
...@@ -19,6 +19,7 @@ import java.io.IOException; ...@@ -19,6 +19,7 @@ import java.io.IOException;
19 import java.io.InputStream; 19 import java.io.InputStream;
20 import java.net.URI; 20 import java.net.URI;
21 import java.net.URISyntaxException; 21 import java.net.URISyntaxException;
22 +import java.util.ArrayList;
22 import java.util.List; 23 import java.util.List;
23 import java.util.stream.StreamSupport; 24 import java.util.stream.StreamSupport;
24 25
...@@ -44,6 +45,10 @@ import org.onosproject.rest.AbstractWebResource; ...@@ -44,6 +45,10 @@ import org.onosproject.rest.AbstractWebResource;
44 import com.fasterxml.jackson.databind.JsonNode; 45 import com.fasterxml.jackson.databind.JsonNode;
45 import com.fasterxml.jackson.databind.node.ArrayNode; 46 import com.fasterxml.jackson.databind.node.ArrayNode;
46 import com.fasterxml.jackson.databind.node.ObjectNode; 47 import com.fasterxml.jackson.databind.node.ObjectNode;
48 +import com.google.common.collect.ArrayListMultimap;
49 +import com.google.common.collect.ListMultimap;
50 +
51 +import static org.onlab.util.Tools.nullIsNotFound;
47 52
48 /** 53 /**
49 * Query and program flow rules. 54 * Query and program flow rules.
...@@ -53,7 +58,10 @@ import com.fasterxml.jackson.databind.node.ObjectNode; ...@@ -53,7 +58,10 @@ import com.fasterxml.jackson.databind.node.ObjectNode;
53 public class FlowsWebResource extends AbstractWebResource { 58 public class FlowsWebResource extends AbstractWebResource {
54 59
55 public static final String DEVICE_NOT_FOUND = "Device is not found"; 60 public static final String DEVICE_NOT_FOUND = "Device is not found";
61 + public static final String FLOW_NOT_FOUND = "Flow is not found";
56 public static final String FLOWS = "flows"; 62 public static final String FLOWS = "flows";
63 + public static final String DEVICE_ID = "deviceId";
64 + public static final String FLOW_ID = "flowId";
57 65
58 final FlowRuleService service = get(FlowRuleService.class); 66 final FlowRuleService service = get(FlowRuleService.class);
59 final ObjectNode root = mapper().createObjectNode(); 67 final ObjectNode root = mapper().createObjectNode();
...@@ -102,10 +110,16 @@ public class FlowsWebResource extends AbstractWebResource { ...@@ -102,10 +110,16 @@ public class FlowsWebResource extends AbstractWebResource {
102 ArrayNode flowsArray = (ArrayNode) jsonTree.get(FLOWS); 110 ArrayNode flowsArray = (ArrayNode) jsonTree.get(FLOWS);
103 List<FlowRule> rules = codec(FlowRule.class).decode(flowsArray, this); 111 List<FlowRule> rules = codec(FlowRule.class).decode(flowsArray, this);
104 service.applyFlowRules(rules.toArray(new FlowRule[rules.size()])); 112 service.applyFlowRules(rules.toArray(new FlowRule[rules.size()]));
113 + rules.forEach(flowRule -> {
114 + ObjectNode flowNode = mapper().createObjectNode();
115 + flowNode.put(DEVICE_ID, flowRule.deviceId().toString())
116 + .put(FLOW_ID, flowRule.id().value());
117 + flowsNode.add(flowNode);
118 + });
105 } catch (IOException ex) { 119 } catch (IOException ex) {
106 throw new IllegalArgumentException(ex); 120 throw new IllegalArgumentException(ex);
107 } 121 }
108 - return Response.ok().build(); 122 + return Response.ok(root).build();
109 } 123 }
110 124
111 /** 125 /**
...@@ -224,4 +238,45 @@ public class FlowsWebResource extends AbstractWebResource { ...@@ -224,4 +238,45 @@ public class FlowsWebResource extends AbstractWebResource {
224 .forEach(service::removeFlowRules); 238 .forEach(service::removeFlowRules);
225 } 239 }
226 240
241 + /**
242 + * Removes a batch of flow rules.
243 + */
244 + @DELETE
245 + @Produces(MediaType.APPLICATION_JSON)
246 + public void deleteFlows(InputStream stream) {
247 + ListMultimap<DeviceId, Long> deviceMap = ArrayListMultimap.create();
248 + List<FlowEntry> rulesToRemove = new ArrayList<>();
249 +
250 + try {
251 + ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
252 +
253 + JsonNode jsonFlows = jsonTree.get("flows");
254 +
255 + jsonFlows.forEach(node -> {
256 + DeviceId deviceId =
257 + DeviceId.deviceId(
258 + nullIsNotFound(node.get(DEVICE_ID),
259 + DEVICE_NOT_FOUND).asText());
260 + long flowId = nullIsNotFound(node.get(FLOW_ID),
261 + FLOW_NOT_FOUND).asLong();
262 + deviceMap.put(deviceId, flowId);
263 +
264 + });
265 + } catch (IOException ex) {
266 + throw new IllegalArgumentException(ex);
267 + }
268 +
269 + deviceMap.keySet().forEach(deviceId -> {
270 + List<Long> flowIds = deviceMap.get(deviceId);
271 + Iterable<FlowEntry> entries = service.getFlowEntries(deviceId);
272 + flowIds.forEach(flowId -> {
273 + StreamSupport.stream(entries.spliterator(), false)
274 + .filter(entry -> flowId == entry.id().value())
275 + .forEach(rulesToRemove::add);
276 + });
277 + });
278 +
279 + service.removeFlowRules(rulesToRemove.toArray(new FlowEntry[0]));
280 + }
281 +
227 } 282 }
......