add more functionality into rest intent

Change-Id: I0c3c89da15c9b48bbe40ef8004db59e33bfdaf12
diff --git a/src/main/java/net/onrc/onos/datagrid/web/DatagridWebRoutable.java b/src/main/java/net/onrc/onos/datagrid/web/DatagridWebRoutable.java
old mode 100644
new mode 100755
index e0e1666..90c7a18
--- a/src/main/java/net/onrc/onos/datagrid/web/DatagridWebRoutable.java
+++ b/src/main/java/net/onrc/onos/datagrid/web/DatagridWebRoutable.java
@@ -18,6 +18,7 @@
         Router router = new Router(context);
         router.attach("/get/map/{map-name}/json", GetMapResource.class);
         router.attach("/add/intent/json", IntentResource.class);
+        router.attach("/get/intents/json", IntentResource.class);
         return router;
     }
 
diff --git a/src/main/java/net/onrc/onos/datagrid/web/IntentResource.java b/src/main/java/net/onrc/onos/datagrid/web/IntentResource.java
index 0d50865..0f552d3 100755
--- a/src/main/java/net/onrc/onos/datagrid/web/IntentResource.java
+++ b/src/main/java/net/onrc/onos/datagrid/web/IntentResource.java
@@ -11,6 +11,7 @@
 import net.onrc.onos.intent.ShortestPathIntent;
 import net.onrc.onos.intent.IntentOperation;
 import net.onrc.onos.intent.IntentMap;
+//import net.onrc.onos.intent.Intent.IntentState;
 import net.onrc.onos.ofcontroller.networkgraph.INetworkGraphService;
 import net.onrc.onos.ofcontroller.networkgraph.NetworkGraph;
 import net.onrc.onos.registry.controller.IControllerRegistryService;
@@ -28,6 +29,8 @@
 import java.util.LinkedList;
 import java.util.Map;
 import org.codehaus.jackson.node.ArrayNode;
+import org.codehaus.jackson.node.ObjectNode;
+import org.restlet.resource.Get;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -43,11 +46,11 @@
 
     private class IntentStatus {
         String intentId;
-        boolean status;
+        String status;
         
         public IntentStatus() {}
         
-        public IntentStatus(String intentId, boolean status) {
+        public IntentStatus(String intentId, String status) {
             this.intentId = intentId;
             this.status = status;
         }
@@ -60,33 +63,28 @@
             this.intentId = intentId;
         }
         
-        public boolean getStatus() {
+        public String getStatus() {
             return status;
         }
         
-        public void setStatus(boolean status) {
+        public void setStatus(String status) {
             this.status = status;
         }
     }
     
     @Post("json")
-    public String store(String jsonFlowIntent) throws IOException {
+    public String store(String jsonIntent) throws IOException {
 	IDatagridService datagridService = (IDatagridService) getContext()
 		.getAttributes().get(IDatagridService.class.getCanonicalName());
 	if (datagridService == null) {
 	    log.debug("FlowIntentResource ONOS Datagrid Service not found");
 	    return "";
 	}
-	INetworkGraphService networkGraphService = (INetworkGraphService) getContext()
-		.getAttributes().get(
-			INetworkGraphService.class.getCanonicalName());
-	NetworkGraph graph = networkGraphService.getNetworkGraph();
         String reply = "";
 	ObjectMapper mapper = new ObjectMapper();
 	JsonNode jNode = null;
 	try {
-	    System.out.println("json string " + jsonFlowIntent);
-	    jNode = mapper.readValue(jsonFlowIntent, JsonNode.class);
+	    jNode = mapper.readValue(jsonIntent, JsonNode.class);
 	} catch (JsonGenerationException ex) {
 	    log.error("JsonGeneration exception ", ex);
 	} catch (JsonMappingException ex) {
@@ -98,11 +96,15 @@
 	if (jNode != null) {
 	    Kryo kryo = new Kryo();
 	    reply = parseJsonNode(kryo, jNode.getElements(), datagridService);
-	    // datagridService.registerIntent(intents);
 	}
         return reply;
     }
 
+    @Get("json")
+    public String retrieve() {
+        return "123";
+    }
+    
     private String parseJsonNode(Kryo kryo, Iterator<JsonNode> nodes,
 	    IDatagridService datagridService) throws IOException {
         LinkedList<IntentOperation> operations = new LinkedList<>();
@@ -119,8 +121,7 @@
 		    data = node.get(fieldName);
                     parseFields(data, fieldName, fields);
 		}
-                System.out.println("recv fields " + fields);
-                boolean status = processIntent(fields, operations);
+                String status = processIntent(fields, operations);
                 appendIntentStatus(status, (String)fields.get("intent_id"), mapper, arrayNode);
 		// datagridService.registerIntent(Long.toString(uuid),
 		// sb.toString().getBytes());
@@ -132,22 +133,25 @@
         
     }
 
-    private void appendIntentStatus(boolean status, final String applnIntentId, 
+    private void appendIntentStatus(String status, final String applnIntentId, 
             ObjectMapper mapper, ArrayNode arrayNode) throws IOException {
+        System.out.println("status " + status);
         String intentId = applnIntentId.split(":")[1];
-        String boolStr = Boolean.TRUE.toString();
-        if (status == false) {
-            boolStr = Boolean.FALSE.toString();
-        }
-        String jsonString = "{\"intent_id\":" + intentId + "," + "\"status\":" + boolStr + "}";
-        JsonNode parsedNode = mapper.readValue(jsonString, JsonNode.class);
-        arrayNode.add(parsedNode);
+        ObjectNode node = mapper.createObjectNode();
+        node.put("intent_id", intentId);
+        node.put("status", status);
+        arrayNode.add(node);
     }
     
-    private boolean processIntent(Map<String, Object> fields, LinkedList<IntentOperation> operations) {
+    private String processIntent(Map<String, Object> fields, LinkedList<IntentOperation> operations) {
         String intentType = (String)fields.get("intent_type");
-        boolean status = false;
+        String intentOp = (String)fields.get("intent_op");
+        String status = null;
         
+        IntentOperation.Operator operation = IntentOperation.Operator.ADD;
+        if ((intentOp.equals("remove"))) {
+            operation = IntentOperation.Operator.REMOVE;
+        }
         if (intentType.equals("shortest_intent_type")) {
             ShortestPathIntent spi = new ShortestPathIntent((String) fields.get("intent_id"),
                     Long.decode((String) fields.get("srcSwitch")),
@@ -156,8 +160,9 @@
                     Long.decode((String) fields.get("dstSwitch")),
                     (long) fields.get("dstPort"),
                     MACAddress.valueOf((String) fields.get("dstMac")).toLong());
-            operations.add(new IntentOperation(IntentOperation.Operator.ADD, spi));
-            status = true;
+            operations.add(new IntentOperation(operation, spi));
+            System.out.println("intent operation " + operation.toString());
+            status = (spi.getState()).toString();
         } else {
             ConstrainedShortestPathIntent cspi = new ConstrainedShortestPathIntent((String) fields.get("intent_id"),
                     Long.decode((String) fields.get("srcSwitch")),
@@ -167,24 +172,20 @@
                     (long) fields.get("dstPort"),
                     MACAddress.valueOf((String) fields.get("dstMac")).toLong(),
                     (double) fields.get("bandwidth"));
-            operations.add(new IntentOperation(IntentOperation.Operator.ADD, cspi));
-            status = true;
+            operations.add(new IntentOperation(operation, cspi));
+            status = (cspi.getState()).toString();
         }
         return status;
     }
 
     private void parseFields(JsonNode node, String fieldName, Map<String, Object> fields) {
         if ((node.isTextual())) {
-            System.out.println("textual fieldname = " + fieldName);
             fields.put(fieldName, node.getTextValue());
         } else if ((node.isInt())) {
-            System.out.println("int fieldname = " + fieldName);
             fields.put(fieldName, (long)node.getIntValue());
         } else if (node.isDouble()) {
-            System.out.println("double fieldname = " + fieldName);
             fields.put(fieldName, node.getDoubleValue());
         } else if ((node.isLong())) {
-            System.out.println("long fieldname = " + fieldName);
             fields.put(fieldName, node.getLongValue());
         }
     }
diff --git a/src/main/java/net/onrc/onos/intent/Intent.java b/src/main/java/net/onrc/onos/intent/Intent.java
index de960f0..3429d1f 100644
--- a/src/main/java/net/onrc/onos/intent/Intent.java
+++ b/src/main/java/net/onrc/onos/intent/Intent.java
@@ -4,7 +4,7 @@
  * @author Toshio Koide (t-koide@onlab.us)
  */
 public class Intent {	
-	enum IntentState {
+	public enum IntentState {
 		CREATED,
 		INST_REQ,
 		INST_NACK,
diff --git a/web/add-intent.rb b/web/add-intent.rb
deleted file mode 100644
index b1d8dfd..0000000
--- a/web/add-intent.rb
+++ /dev/null
@@ -1,122 +0,0 @@
-require "rest-client"
-require "optparse"
-
-options = { :intent_id => 123, :intent_type => "shortest_intent_type", :max_switches => 4 }
-
-parser = OptionParser.new do |opts|
-  opts.banner = "Usage add-intent [options]"
-  opts.on('-t', '--max_intents max_intents', 'max. number of intents') do |max_intents|
-    options[:max_intents] = max_intents
-  end
-  opts.on('-a', '--application application_id', 'set application id') do |appl_id|
-    options[:application_id] = appl_id.to_i
-  end
-  opts.on('-i', '--intent_id intent_id', 'global intent id') do |id|
-    options[:intent_id] = id.to_i
-  end
-  opts.on('-s', '--shortest', 'create a shortest path intent') do
-    options[:intent_type] = "shortest_intent_type"
-  end
-  opts.on('-c', '--constrained', 'create a constrained shortest path intent') do
-    options[:intent_type] = "constrained_shortest_intent_type"
-  end
-  opts.on('-m', '--max_switches max_switches', 'max. number of switches') do |max_switches|
-    options[:max_switches] = max_switches.to_i
-  end
-  opts.on('-h', '--help', 'Display help') do
-    puts opts
-    exit
-  end
-end
-parser.parse!
-
-puts options.inspect
-server = options[:server]
-server ||= "127.0.0.1"
-port = options[:port]
-port ||= 8080
-
-def rand_mac
-  mac = `openssl rand -hex 6`
-  mac.scan(/(..)/).join(":")
-end
-
-def rand_switch
-  switch = `openssl rand -hex 5`.chomp
-end
-
-class Intent
-  attr_reader :switches
-  attr_reader :ports
-  attr_reader :intent_id
-  attr_reader :application_id
-  attr_reader :intent_type
-
-  def initialize options
-    parse_options options
-  end
-
-  def create_intent 
-    json_intents = []
-    @switches.each do |sw|
-      rest = switches - [sw]
-      json_intents = _create_intent sw, rest, json_intents
-    end
-    json_intents
-  end
-
-  def parse_options options
-    max_switches = options[:max_switches].to_i || 4
-    @switches = (1..max_switches).to_a
-    @ports = (1..(max_switches - 1)).to_a
-    @intent_id = options[:intent_id]
-    @intent_id ||= 1
-    @application_id = options[:application_id]
-    @application_id ||= 1
-    @intent_type = options[:intent_type]
-  end
-
-
-  def _create_intent src_switch, iterable_switches, json_intents
-    network_id = 1
-    iterable_switches.each_index do |sw_i|
-      dst_switch = iterable_switches[sw_i]
-      sw_set = @switches - [dst_switch]
-      dst_port = sw_set.index(src_switch)
-      dst_port = dst_port + 1
-      intent = {
-        :intent_id => "#{@application_id}:#{@intent_id}",
-        :intent_type => @intent_type,
-        :srcSwitch => src_switch.to_s,
-        :srcPort => @ports[sw_i],
-        :srcMac => "00:00:c0:a8:#{mac_format(src_switch)}",
-        :dstSwitch => iterable_switches[sw_i].to_s,
-        :dstPort => dst_port,
-        :dstMac => "00:00:c0:a8:#{mac_format(iterable_switches[sw_i].to_i)}"
-      }
-puts intent
-      @intent_id = @intent_id + 1
-      json_intents << intent
-puts
-    end
-    #sha256 = Digest::SHA256.new
-    #sha256.update intent_hash.to_s
-    #puts sha256.hexdigest
-    #puts "intent hash = #{intent_hash}"
-    json_intents
-  end
-
-  def mac_format number
-    if number > 255
-      divisor = number / 256 
-      remainder = number % 256
-      return sprintf("%02x:%02x",divisor ,remainder)
-    end
-    "00:%02x" % number
-  end
-end
-
-intent = Intent.new options
-json_data = intent.create_intent
-response = RestClient.post "http://#{server}:#{port}/wm/onos/datagrid/add/intent/json", json_data.to_json, :content_type => :json, :accept => :json
-puts response.inspect
diff --git a/web/rest-intent/add-get-intent.rb b/web/rest-intent/add-get-intent.rb
new file mode 100644
index 0000000..1627aea
--- /dev/null
+++ b/web/rest-intent/add-get-intent.rb
@@ -0,0 +1,207 @@
+require "rest-client"
+require "optparse"
+
+options = { 
+  :rest_op => "add",
+  :intent_id => 123, 
+  :intent_type => "shortest_intent_type", 
+  :max_switches => 4,
+  :intent_op => "add"
+}
+
+parser = OptionParser.new do |opts|
+  opts.banner = "Usage add-get-intent [options]"
+  opts.on('-g', '--get_intents', 'get intents state') do
+    options[:rest_op] = "get"
+  end
+  opts.on('-t', '--max_intents max_intents', 'max. number of intents') do |max_intents|
+    options[:max_intents] = max_intents
+  end
+  opts.on('-l', '--application application_id', 'set application id') do |appl_id|
+    options[:application_id] = appl_id.to_i
+  end
+  opts.on('-i', '--intent_id intent_id', 'global intent id') do |id|
+    options[:intent_id] = id.to_i
+  end
+  # optional argument
+  opts.on('-s', '--shortest', 'create a shortest path intent') do
+    options[:intent_type] = "shortest_intent_type"
+  end
+  # optional argument
+  opts.on('-c', '--constrained', 'create a constrained shortest path intent') do
+    options[:intent_type] = "constrained_shortest_intent_type"
+  end
+  # optional argument
+  opts.on('-r', '--random_intent', 'create minimum no. of random intents') do
+    options[:random_intent] = true
+  end
+  opts.on('-m', '--max_switches max_switches', 'max. number of switches') do |max_switches|
+    options[:max_switches] = max_switches.to_i
+  end
+  opts.on('-o', '--intent_op add|remove', 'an operation to post an intent') do |operation|
+    options[:intent_op] = operation
+  end
+  opts.on('-w', '--server server', 'server to post intents') do |server|
+    options[:server] = server
+  end
+  opts.on('-p','--port port', 'server port') do |port|
+    options[:port] = port
+  end
+  opts.on('b', '--bulk_limit bulk_limit', 'bulk request upto this limit') do |bulk_limit|
+    options[:bulk_limit] = bulk_limit
+  end
+  opts.on('-h', '--help', 'Display help') do
+    puts opts
+    exit
+  end
+end
+parser.parse!
+
+def rand_mac
+  mac = `openssl rand -hex 6`
+  mac.scan(/(..)/).join(":")
+end
+
+def rand_switch
+  switch = `openssl rand -hex 5`.chomp
+end
+
+class Intent
+  attr_reader :switches, :ports, :intent_id
+  attr_reader :application_id, :intent_type, :intent_op
+  attr_reader :random_intent, :server, :port
+  attr_reader :bulk_limit
+
+  def initialize options
+    parse_options options
+  end
+
+  def post_intent 
+    create_specific_intent
+  end
+
+  def get_intent
+    request = RestClient.get "http://#{@server}:#{@port}/wm/onos/datagrid/get/intents/json"
+    puts request
+  end
+
+  private 
+
+  def create_specific_intent
+    if @random_intent == true
+      create_random_intent
+    else
+      create_many_intents
+    end
+  end
+
+  # create as many intents as the number of switches
+  def create_many_intents
+    intents = []
+    @switches.each do |sw|
+      rest = @switches - [sw]
+      intents = _create_intent sw, rest, intents
+puts intents.size
+      post_slice intents
+    end
+    post_slice intents, true
+  end
+
+  # pick a random src switch and create intents to all other switches
+  def create_random_intent
+    intents = []
+    sw = @switches.shuffle[0]
+    rest = @switches - [sw]
+    intents = _create_intent sw, rest, intents
+    post_slice intents, true
+  end
+
+  def post_slice intents, last=false
+    @bulk_limit = @bulk_limit.to_i
+    if intents.size >= @bulk_limit
+      post intents.slice!(0..(@bulk_limit - 1))
+    end
+    if last == true
+      loop do
+        new_bulk_limit = intents.size > @bulk_limit ? @bulk_limit : intents.size
+        post intents.slice!(0..(new_bulk_limit - 1))
+        break if new_bulk_limit < @bulk_limit
+      end
+    end
+  end
+
+  def post intents
+    json_data = intents.to_json
+    response = RestClient.post "http://#{@server}:#{@port}/wm/onos/datagrid/#{intent_op}/intent/json", json_data, :content_type => :json, :accept => :json
+    puts response
+  end
+
+  def parse_options options
+    max_switches = options[:max_switches].to_i || 4
+    @switches = (1..max_switches).to_a
+    @ports = (1..(max_switches - 1)).to_a
+    @intent_id = options[:intent_id]
+    @intent_id ||= 1
+    @application_id = options[:application_id]
+    @application_id ||= 1
+    @intent_type = options[:intent_type]
+    @intent_op = options[:intent_op]
+    @intent_op ||= "add"
+    @random_intent = options[:random_intent]
+    @random_intent ||= false
+    @server = options[:server]
+    @server ||= "127.0.0.1"
+    @port = options[:port]
+    @port ||= 8080
+    @bulk_limit = options[:bulk_limit]
+    @bulk_limit ||= 10000
+  end
+
+
+  def _create_intent src_switch, iterable_switches, json_intents
+    network_id = 1
+    iterable_switches.each_index do |sw_i|
+      dst_switch = iterable_switches[sw_i]
+      sw_set = @switches - [dst_switch]
+      dst_port = sw_set.index(src_switch)
+      dst_port = dst_port + 1
+      intent = {
+        :intent_id => "#{@application_id}:#{@intent_id}",
+        :intent_type => @intent_type,
+        :intent_op => @intent_op,
+        :srcSwitch => src_switch.to_s,
+        :srcPort => @ports[sw_i],
+        :srcMac => "00:00:c0:a8:#{mac_format(src_switch)}",
+        :dstSwitch => iterable_switches[sw_i].to_s,
+        :dstPort => dst_port,
+        :dstMac => "00:00:c0:a8:#{mac_format(iterable_switches[sw_i].to_i)}"
+      }
+puts intent.inspect
+      @intent_id = @intent_id + 1
+      json_intents << intent
+puts
+    end
+    #sha256 = Digest::SHA256.new
+    #sha256.update intent_hash.to_s
+    #puts sha256.hexdigest
+    #puts "intent hash = #{intent_hash}"
+    json_intents
+  end
+
+  def mac_format number
+    if number > 255
+      divisor = number / 256 
+      remainder = number % 256
+      return sprintf("%02x:%02x",divisor ,remainder)
+    end
+    "00:%02x" % number
+  end
+end
+
+intent = Intent.new options
+if options[:rest_op] == "get"
+  intent.get_intent
+else
+  json_data = intent.post_intent
+end
+