Added shortest-path computation tool:

admin@deva-onos1:~/ONOS/web$ ./get_network_graph.py shortest-path 00:00:00:00:00:00:02:01 00:00:00:00:00:00:04:01
[
    {
        "src-switch": "00:00:00:00:00:00:02:01",
        "src-port": 51,
        "dst-switch": "00:00:00:00:00:00:01:02",
        "dst-port": 4
    },
    {
        "src-switch": "00:00:00:00:00:00:01:02",
        "src-port": 3,
        "dst-switch": "00:00:00:00:00:00:01:03",
        "dst-port": 2
    },
    {
        "src-switch": "00:00:00:00:00:00:01:03",
        "src-port": 3,
        "dst-switch": "00:00:00:00:00:00:01:04",
        "dst-port": 2
    },
    {
        "src-switch": "00:00:00:00:00:00:01:04",
        "src-port": 5,
        "dst-switch": "00:00:00:00:00:00:04:01",
        "dst-port": 26
    }
]

Removed extra (empty) new line in the web/get_datagrid_ngevents.py output

Change-Id: I5ac8981447fbe26a26b812e8d811f902665123d7
diff --git a/src/main/java/net/onrc/onos/ofcontroller/networkgraph/web/NetworkGraphShortestPathResource.java b/src/main/java/net/onrc/onos/ofcontroller/networkgraph/web/NetworkGraphShortestPathResource.java
new file mode 100644
index 0000000..43e5806
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/networkgraph/web/NetworkGraphShortestPathResource.java
@@ -0,0 +1,81 @@
+package net.onrc.onos.ofcontroller.networkgraph.web;
+
+import java.io.IOException;
+import java.util.LinkedList;
+import java.util.List;
+
+import net.onrc.onos.intent.ConstrainedBFSTree;
+import net.onrc.onos.ofcontroller.networkgraph.INetworkGraphService;
+import net.onrc.onos.ofcontroller.networkgraph.Link;
+import net.onrc.onos.ofcontroller.networkgraph.LinkEvent;
+import net.onrc.onos.ofcontroller.networkgraph.NetworkGraph;
+import net.onrc.onos.ofcontroller.networkgraph.Path;
+import net.onrc.onos.ofcontroller.networkgraph.Switch;
+import net.onrc.onos.ofcontroller.networkgraph.serializers.LinkSerializer;
+import net.onrc.onos.ofcontroller.util.Dpid;
+
+import org.codehaus.jackson.Version;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.codehaus.jackson.map.module.SimpleModule;
+import org.restlet.resource.Get;
+import org.restlet.resource.ServerResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class NetworkGraphShortestPathResource extends ServerResource {
+
+    private static final Logger log = LoggerFactory.getLogger(NetworkGraphShortestPathResource.class);
+
+    @Get("json")
+    public String retrieve() {
+	INetworkGraphService networkGraphService =
+	    (INetworkGraphService)getContext().getAttributes().
+	    get(INetworkGraphService.class.getCanonicalName());
+
+	NetworkGraph graph = networkGraphService.getNetworkGraph();
+
+	ObjectMapper mapper = new ObjectMapper();
+	SimpleModule module = new SimpleModule("module", new Version(1, 0, 0, null));
+	module.addSerializer(new LinkSerializer());
+	mapper.registerModule(module);
+
+	//
+	// Fetch the attributes
+	//
+	String srcDpidStr = (String)getRequestAttributes().get("src-dpid");
+	String dstDpidStr = (String)getRequestAttributes().get("dst-dpid");
+	Dpid srcDpid = new Dpid(srcDpidStr);
+	Dpid dstDpid = new Dpid(dstDpidStr);
+	log.debug("Getting Shortest Path {}--{}", srcDpidStr, dstDpidStr);
+
+	//
+	// Do the Shortest Path computation and return the result: list of
+	// links.
+	//
+	try {
+	    graph.acquireReadLock();
+	    Switch srcSwitch = graph.getSwitch(srcDpid.value());
+	    Switch dstSwitch = graph.getSwitch(dstDpid.value());
+	    if ((srcSwitch == null) || (dstSwitch == null))
+		return "";
+	    ConstrainedBFSTree bfsTree = new ConstrainedBFSTree(srcSwitch);
+	    Path path = bfsTree.getPath(dstSwitch);
+	    List<Link> links = new LinkedList<>();
+	    for (LinkEvent linkEvent : path) {
+		Link link = graph.getLink(linkEvent.getSrc().getDpid(),
+					  linkEvent.getSrc().getNumber(),
+					  linkEvent.getDst().getDpid(),
+					  linkEvent.getDst().getNumber());
+		if (link == null)
+		    return "";
+		links.add(link);
+	    }
+	    return mapper.writeValueAsString(links);
+	} catch (IOException e) {
+	    log.error("Error writing Shortest Path to JSON", e);
+	    return "";
+	} finally {
+	    graph.releaseReadLock();
+	}
+    }
+}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/networkgraph/web/NetworkGraphWebRoutable.java b/src/main/java/net/onrc/onos/ofcontroller/networkgraph/web/NetworkGraphWebRoutable.java
index 6a7ab99..e245801 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/networkgraph/web/NetworkGraphWebRoutable.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/networkgraph/web/NetworkGraphWebRoutable.java
@@ -16,6 +16,7 @@
 		router.attach("/rc/ports/json", RamcloudPortsResource.class);
 		router.attach("/ng/switches/json", NetworkGraphSwitchesResource.class);
 		router.attach("/ng/links/json", NetworkGraphLinksResource.class);
+		router.attach("/ng/shortest-path/{src-dpid}/{dst-dpid}/json", NetworkGraphShortestPathResource.class);
 		return router;
 	}
 
diff --git a/web/get_datagrid_ngevents.py b/web/get_datagrid_ngevents.py
index 34c3338..f7ef7d4 100755
--- a/web/get_datagrid_ngevents.py
+++ b/web/get_datagrid_ngevents.py
@@ -33,7 +33,7 @@
 # Sample output:
 
 def print_datagrid_map(parsedResult):
-  print '%s' % (parsedResult)
+  print '%s' % (parsedResult),
 
 def get_datagrid_map():
   try:
diff --git a/web/get_network_graph.py b/web/get_network_graph.py
index ed3292b..375e5ff 100755
--- a/web/get_network_graph.py
+++ b/web/get_network_graph.py
@@ -2,7 +2,10 @@
 # -*- Mode: python; py-indent-offset: 4; tab-width: 8; indent-tabs-mode: t; -*-
 
 #
-# Get Network Graph Elements
+# Get Network Graph Information:
+#  - Switches
+#  - Links
+#  - Shortest Path
 #
 
 import pprint
@@ -10,6 +13,7 @@
 import sys
 import subprocess
 import json
+import collections
 import argparse
 import io
 import time
@@ -35,6 +39,7 @@
 
 # @app.route("/wm/onos/ng/links/json ")
 # @app.route("/wm/onos/ng/switches/json ")
+# @app.route("/wm/onos/ng/shortest-path/<src-dpid>/<dst-dpid>/json ")
 # Sample output:
 
 def print_parsed_result(parsedResult):
@@ -82,16 +87,39 @@
 
   print_parsed_result(parsedResult)
 
+def get_network_shortest_path(src_dpid, dst_dpid):
+  try:
+    command = "curl -s \"http://%s:%s/wm/onos/ng/shortest-path/%s/%s/json\"" % (ControllerIP, ControllerPort, src_dpid, dst_dpid)
+    debug("get_network_switches %s" % command)
+
+    result = os.popen(command).read()
+    debug("result %s" % result)
+    if len(result) == 0:
+      print "No Path found"
+      return;
+
+    # parsedResult = result
+    parsedResult = json.loads(result, object_pairs_hook=collections.OrderedDict)
+    parsedResult = json.dumps(parsedResult, indent=4)
+    debug("parsed %s" % parsedResult)
+  except:
+    log_error("Controller IF has issue")
+    exit(1)
+
+  print_parsed_result(parsedResult)
+
 
 if __name__ == "__main__":
   usage_msg1 = "Usage:\n"
-  usage_msg2 = "%s <elements_name> : Print network elements with name of <elements_name>\n" % (sys.argv[0])
-  usage_msg3 = "    Valid element names:\n"
-  usage_msg4 = "        all              : Print all network elements\n"
-  usage_msg5 = "        switches         : Print all switches and ports\n"
-  usage_msg6 = "        links            : Print all links\n"
+  usage_msg2 = "%s <arguments> : Print network information\n" % (sys.argv[0])
+  usage_msg3 = "  Valid element names:\n"
+  usage_msg4 = "    all              : Print all network elements\n"
+  usage_msg5 = "    switches         : Print all switches and ports\n"
+  usage_msg6 = "    links            : Print all links\n"
+  usage_msg7 = "    shortest-path <src-dpid> <dst-dpid> : Print shortest-path\n"
+  usage_msg8 = "                                      (links between <src-dpid> and <dst-dpid>)\n"
   usage_msg = usage_msg1 + usage_msg2 + usage_msg3 + usage_msg4 + usage_msg5
-  usage_msg = usage_msg + usage_msg6
+  usage_msg = usage_msg + usage_msg6 + usage_msg7 + usage_msg8
 
   # Usage info
   if len(sys.argv) > 1 and (sys.argv[1] == "-h" or sys.argv[1] == "--help"):
@@ -103,12 +131,19 @@
     log_error(usage_msg)
     exit(1)
 
-  if (sys.argv[1] != "all" and sys.argv[1] != "switches" and sys.argv[1] != "links"):
+  if (sys.argv[1] != "all" and sys.argv[1] != "switches" and sys.argv[1] != "links" and sys.argv[1] != "shortest-path"):
     log_error(usage_msg)
     exit(1)
 
+  if (sys.argv[1] == "shortest-path"):
+    if len(sys.argv) < 4:
+      log_error(usage_msg)
+      exit(1)
+
   # Do the work
   if (sys.argv[1] == "all" or sys.argv[1] == "switches"):
     get_network_switches()
   if (sys.argv[1] == "all" or sys.argv[1] == "links"):
     get_network_links()
+  if (sys.argv[1] == "shortest-path"):
+    get_network_shortest_path(sys.argv[2], sys.argv[3])