Added REST API and CLI for FlowSynchronizer.
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/web/DoInterruptResource.java b/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/web/DoInterruptResource.java
new file mode 100644
index 0000000..3c2920d
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/web/DoInterruptResource.java
@@ -0,0 +1,44 @@
+package net.onrc.onos.ofcontroller.flowprogrammer.web;
+
+import net.floodlightcontroller.core.IOFSwitch;
+
+import org.openflow.util.HexString;
+import org.restlet.resource.Get;
+
+/**
+ * FlowProgrammer REST API implementation: Interrupt synchronization to a switch.
+ *
+ *   GET /wm/fprog/synchronizer/interrupt/{dpid}/json"
+ */
+public class DoInterruptResource extends SynchronizerResource {
+
+    /**
+     * Implement the API.
+     *
+     * @return true if succeeded, false if failed.
+     */
+    @Get("json")
+    public boolean retrieve() {
+    	if (! init()) {
+    		return false;
+    	}
+    	
+    	long dpid;
+    	try {
+    		dpid = HexString.toLong((String)getRequestAttributes().get("dpid"));
+    	} catch (NumberFormatException e) {
+    		log.error("Invalid number format");
+    		return false;
+    	}
+
+    	IOFSwitch sw = provider.getSwitches().get(dpid);
+    	if (sw == null) {
+    		log.error("Invalid dpid");
+    		return false;
+    	}
+    	
+    	synchronizer.interrupt(sw);
+    	
+    	return true;
+    }
+}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/web/DoSynchronizeResource.java b/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/web/DoSynchronizeResource.java
new file mode 100644
index 0000000..dc8d431
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/web/DoSynchronizeResource.java
@@ -0,0 +1,44 @@
+package net.onrc.onos.ofcontroller.flowprogrammer.web;
+
+import net.floodlightcontroller.core.IOFSwitch;
+
+import org.openflow.util.HexString;
+import org.restlet.resource.Get;
+
+/**
+ * FlowProgrammer REST API implementation: Begin synchronization to a switch.
+ *
+ *   GET /wm/fprog/synchronizer/sync/{dpid}/json"
+ */
+public class DoSynchronizeResource extends SynchronizerResource {
+    /**
+     * Implement the API.
+     *
+     * @return true if succeeded, false if failed.
+     */
+    @Get("json")
+    public boolean retrieve() {
+    	if (! init()) {
+    		return false;
+    	}
+    	
+    	long dpid;
+    	try {
+    		dpid = HexString.toLong((String)getRequestAttributes().get("dpid"));
+    	} catch (NumberFormatException e) {
+    		log.error("Invalid number format");
+    		return false;
+    	}
+
+    	IOFSwitch sw = provider.getSwitches().get(dpid);
+    	if (sw == null) {
+    		log.error("Invalid dpid");
+    		return false;
+    	}
+    	
+    	synchronizer.synchronize(sw);
+    	
+    	return true;
+    }
+
+}
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/web/FlowProgrammerWebRoutable.java b/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/web/FlowProgrammerWebRoutable.java
index 00d7fc9..22450f7 100644
--- a/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/web/FlowProgrammerWebRoutable.java
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/web/FlowProgrammerWebRoutable.java
@@ -15,6 +15,8 @@
 		router.attach("/pusher/suspend/{dpid}/json", SuspendPusherResource.class);
 		router.attach("/pusher/resume/{dpid}/json", ResumePusherResource.class);
 		router.attach("/pusher/barrier/{dpid}/json", SendBarrierResource.class);
+		router.attach("/synchronizer/sync/{dpid}/json", DoSynchronizeResource.class);
+		router.attach("/synchronizer/interrupt/{dpid}/json", DoInterruptResource.class);
 		return router;
 	}
 
diff --git a/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/web/SynchronizerResource.java b/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/web/SynchronizerResource.java
new file mode 100644
index 0000000..12bf8f3
--- /dev/null
+++ b/src/main/java/net/onrc/onos/ofcontroller/flowprogrammer/web/SynchronizerResource.java
@@ -0,0 +1,35 @@
+package net.onrc.onos.ofcontroller.flowprogrammer.web;
+
+import net.floodlightcontroller.core.IFloodlightProviderService;
+import net.onrc.onos.ofcontroller.flowprogrammer.IFlowSyncService;
+
+import org.restlet.resource.ServerResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SynchronizerResource extends ServerResource {
+    protected final static Logger log = LoggerFactory.getLogger(SynchronizerResource.class);
+    
+    protected IFloodlightProviderService provider;
+    protected IFlowSyncService synchronizer;
+
+    protected boolean init() {
+    	provider = (IFloodlightProviderService)
+    			getContext().getAttributes().
+    			get(IFloodlightProviderService.class.getCanonicalName());
+    	if (provider == null) {
+		    log.debug("ONOS FloodlightProvider not found");
+		    return false;
+		}
+    	
+    	synchronizer = (IFlowSyncService)
+    			getContext().getAttributes().
+    			get(IFlowSyncService.class.getCanonicalName());
+    	if (synchronizer == null) {
+		    log.debug("ONOS FlowSyncService not found");
+		    return false;
+		}
+    	
+    	return true;
+    }
+}
diff --git a/web/flowsync.py b/web/flowsync.py
new file mode 100755
index 0000000..51399d5
--- /dev/null
+++ b/web/flowsync.py
@@ -0,0 +1,103 @@
+#! /usr/bin/env python
+
+
+import pprint
+import os
+import sys
+import subprocess
+import json
+import argparse
+import io
+import time
+
+from flask import Flask, json, Response, render_template, make_response, request
+
+## Global Var ##
+ControllerIP="127.0.0.1"
+ControllerPort=8080
+
+DEBUG=0
+pp = pprint.PrettyPrinter(indent=4)
+
+app = Flask(__name__)
+
+## Worker Functions ##
+def log_error(txt):
+  print '%s' % (txt)
+
+def debug(txt):
+  if DEBUG:
+    print '%s' % (txt)
+
+# @app.route("/wm/fprog/synchronizer/sync/<dpid>/json")
+# Sample output:
+#  "true"
+def synchronize(dpid):
+  try:
+    command = "curl -s \"http://%s:%s/wm/fprog/synchronizer/sync/%s/json\"" % (ControllerIP, ControllerPort, dpid)
+    debug("synchronize %s" % command)
+     
+    result = os.popen(command).read()
+    debug("result %s" % result)
+    if result == "false":
+      print "Failed to synchronize"
+      return;
+  except:
+    log_error("Controller IF has issue")
+    exit(1)
+  
+  print "Synchronization of switch %s has successfully began" % (dpid)
+
+# @app.route("/wm/fprog/synchronizer/interrupt/<dpid>/json")
+# Sample output:
+#  "true"
+def interrupt(dpid):
+  try:
+    command = "curl -s \"http://%s:%s/wm/fprog/synchronizer/interrupt/%s/json\"" % (ControllerIP, ControllerPort, dpid)
+    debug("interrupt %s" % command)
+     
+    result = os.popen(command).read()
+    debug("result %s" % result)
+    if result == "false":
+      print "Failed to interrupt synchronization"
+      return;
+  except:
+    log_error("Controller IF has issue")
+    exit(1)
+  
+  print "Synchronization of switch %s has successfully interrupted" % (dpid)
+
+
+if __name__ == "__main__":
+  usage_msg1 = "Usage:\n"
+  usage_msg2 = "%s sync <dpid>      : Start synchronization of the switch\n" % (sys.argv[0])
+  usage_msg3 = "                interrupt <dpid> : Interrupt synchronization of the switch\n"
+  usage_msg = usage_msg1 + usage_msg2 + usage_msg3;
+  
+  app.debug = True;
+
+  # Usage info
+  if len(sys.argv) > 1 and (sys.argv[1] == "-h" or sys.argv[1] == "--help"):
+    print(usage_msg)
+    exit(0)
+
+  # Check arguments
+  if len(sys.argv) < 2:
+    log_error(usage_msg)
+    exit(1)
+
+  # Do the work
+  if sys.argv[1] == "sync":
+    if len(sys.argv) < 3:
+      log_error(usage_msg)
+      exit(1)
+    synchronize(sys.argv[2])
+  elif sys.argv[1] == "interrupt":
+    if len(sys.argv) < 3:
+      log_error(usage_msg)
+      exit(1)
+    interrupt(sys.argv[2])
+  else:
+    log_error(usage_msg)
+    exit(1)
+ 
\ No newline at end of file