diff --git a/src/main/java/net/floodlightcontroller/core/IFloodlightProviderService.java b/src/main/java/net/floodlightcontroller/core/IFloodlightProviderService.java
index a24f774cbe051d4a27020c9054aedd0ced94474f..be61662c5e190993b8b0a63efd79faa4df1a6413 100644
--- a/src/main/java/net/floodlightcontroller/core/IFloodlightProviderService.java
+++ b/src/main/java/net/floodlightcontroller/core/IFloodlightProviderService.java
@@ -68,6 +68,12 @@ public interface IFloodlightProviderService extends IFloodlightService {
      * @param listener The component that no longer wants to receive the message
      */
     public void removeOFMessageListener(OFType type, IOFMessageListener listener);
+    
+    /**
+     * Return a non-modifiable list of all current listeners
+     * @return listeners
+     */
+    public Map<OFType, List<IOFMessageListener>> getListeners();
 
     /**
      * Returns a list of all actively connected OpenFlow switches. This doesn't
@@ -81,6 +87,11 @@ public interface IFloodlightProviderService extends IFloodlightService {
      */
     public Role getRole();
     
+    /**
+     * Gets the ID of the controller
+     */
+    public String getControllerId();
+    
     /**
      * Set the role of the controller
      */
@@ -88,21 +99,27 @@ public interface IFloodlightProviderService extends IFloodlightService {
     
     /**
      * Add a switch listener
-     * @param listener
+     * @param listener The module that wants to listen for events
      */
     public void addOFSwitchListener(IOFSwitchListener listener);
 
     /**
      * Remove a switch listener
-     * @param listener
+     * @param listener The The module that no longer wants to listen for events
      */
     public void removeOFSwitchListener(IOFSwitchListener listener);
-
+    
     /**
-     * Return a non-modifiable list of all current listeners
-     * @return listeners
+     * Adds a listener for HA role events
+     * @param listener The module that wants to listen for events
      */
-    public Map<OFType, List<IOFMessageListener>> getListeners();
+    public void addHAListener(IHARoleListener listener);
+    
+    /**
+     * Removes a listener for HA role events
+     * @param listener The module that no longer wants to listen for events
+     */
+    public void removeHAListener(IHARoleListener listener);
 
     /**
      * Terminate the process
diff --git a/src/main/java/net/floodlightcontroller/core/IHARoleListener.java b/src/main/java/net/floodlightcontroller/core/IHARoleListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..83749caed0d7e33fb2d177d4837d43b2d95f5d97
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/core/IHARoleListener.java
@@ -0,0 +1,13 @@
+package net.floodlightcontroller.core;
+
+import net.floodlightcontroller.core.IFloodlightProviderService.Role;
+
+public interface IHARoleListener {
+    /**
+     * Gets called when the controller changes role (i.e. Master -> Slave).
+     * Note that oldRole CAN be null.
+     * @param oldRole The controller's old role
+     * @param newRole The controller's new role
+     */
+    public void roleChanged(Role oldRole, Role newRole);
+}
diff --git a/src/main/java/net/floodlightcontroller/core/internal/Controller.java b/src/main/java/net/floodlightcontroller/core/internal/Controller.java
index 590d0c353b34ee161f1e1b09248d088e57de6dc7..9876d2547078e6887d1597dce71f8e43fe1a8f27 100644
--- a/src/main/java/net/floodlightcontroller/core/internal/Controller.java
+++ b/src/main/java/net/floodlightcontroller/core/internal/Controller.java
@@ -17,7 +17,6 @@
 
 package net.floodlightcontroller.core.internal;
 
-import java.io.FileInputStream;
 import java.io.IOException;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
@@ -32,7 +31,6 @@ import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
-import java.util.Properties;
 import java.util.Set;
 import java.util.Stack;
 import java.util.concurrent.BlockingQueue;
@@ -48,6 +46,7 @@ import java.util.concurrent.TimeoutException;
 
 import net.floodlightcontroller.core.FloodlightContext;
 import net.floodlightcontroller.core.IFloodlightProviderService;
+import net.floodlightcontroller.core.IHARoleListener;
 import net.floodlightcontroller.core.IInfoProvider;
 import net.floodlightcontroller.core.IOFMessageListener;
 import net.floodlightcontroller.core.IOFMessageListener.Command;
@@ -146,6 +145,7 @@ public class Controller implements IFloodlightProviderService {
     protected ConcurrentHashMap<Long, IOFSwitch> connectedSwitches;
     
     protected Set<IOFSwitchListener> switchListeners;
+    protected Set<IHARoleListener> haListeners;
     protected Map<String, List<IInfoProvider>> providerMap;
     protected BlockingQueue<Update> updates;
     
@@ -159,6 +159,7 @@ public class Controller implements IFloodlightProviderService {
     // Configuration options
     protected int openFlowPort = 6633;
     protected int workerThreads = 0;
+    protected String controllerId = "localhost";
     
     // The current role of the controller.
     // If the controller isn't configured to support roles, then this is null.
@@ -199,13 +200,26 @@ public class Controller implements IFloodlightProviderService {
     protected static final int BATCH_MAX_SIZE = 100;
     protected static final boolean ALWAYS_DECODE_ETH = true;
 
+    protected enum UpdateType {
+        SWITCH, HA
+    }
     protected class Update {
+        public UpdateType type;
         public IOFSwitch sw;
         public boolean added;
+        public Role oldRole;
+        public Role newRole;
 
         public Update(IOFSwitch sw, boolean added) {
             this.sw = sw;
             this.added = added;
+            this.type = UpdateType.SWITCH;
+        }
+        
+        public Update(Role newRole, Role oldRole) {
+            this.oldRole = oldRole;
+            this.newRole = newRole;
+            this.type = UpdateType.HA;
         }
     }
     
@@ -240,6 +254,8 @@ public class Controller implements IFloodlightProviderService {
     
     @Override
     public synchronized void setRole(Role role) {
+        if (role == null) throw new NullPointerException("Role can not be null.");
+        Role oldRole = this.role;
         this.role = role;
         
         // Send role request messages to all of the connected switches.
@@ -256,8 +272,8 @@ public class Controller implements IFloodlightProviderService {
             }
         }
         
-        // Send an update
-        // TODO send update
+        // Enqueue an update for our listeners.
+        this.updates.add(new Update(role, oldRole));
     }
     
     /**
@@ -1368,8 +1384,9 @@ public class Controller implements IFloodlightProviderService {
         return factory;
     }
     
+    @Override
     public String getControllerId() {
-        return "localhost";
+        return controllerId;
     }
     
     // **************
@@ -1521,25 +1538,13 @@ public class Controller implements IFloodlightProviderService {
         storageSource.deleteRowAsync(PORT_TABLE_NAME, id);
     }
 
-    protected Role getInitialRole() {
-        // FIXME: This code should be changed to get the settings from
-        // the property file used by the module loader once Alex has
-        // that code written instead of using system properties.
+    /**
+     * Sets the role based on a string.
+     * @param roleString The role string
+     * @return The role is a valid string is passed, nulll otherwise
+     */
+    protected Role getInitialRole(String roleString) {
         Role role = null;
-        String roleString = System.getProperty("floodlight.role");
-        if (roleString == null) {
-            String rolePath = System.getProperty("floodlight.role.path");
-            if (rolePath != null) {
-                Properties properties = new Properties();
-                try {
-                    properties.load(new FileInputStream(rolePath));
-                    roleString = properties.getProperty("floodlight.role");
-                }
-                catch (IOException exc) {
-                    log.error("Error reading current role value from file: {}", rolePath);
-                }
-            }
-        }
         
         if (roleString != null) {
             // Canonicalize the string to the form used for the enum constants
@@ -1552,6 +1557,7 @@ public class Controller implements IFloodlightProviderService {
             }
         }
         
+        log.info("Controller roles set to {}", role);
         return role;
     }
     
@@ -1584,15 +1590,35 @@ public class Controller implements IFloodlightProviderService {
         while (true) {
             try {
                 Update update = updates.take();
-                log.debug("Dispatching switch update {} {}",
-                          update.sw, update.added);
-                if (switchListeners != null) {
-                    for (IOFSwitchListener listener : switchListeners) {
-                        if (update.added)
-                            listener.addedSwitch(update.sw);
-                        else
-                            listener.removedSwitch(update.sw);
-                    }
+                switch (update.type) {
+                    case SWITCH:
+                        if (log.isDebugEnabled()) {
+                            log.debug("Dispatching switch update {} {}",
+                                      update.sw, update.added);
+                        }
+                        if (switchListeners != null) {
+                            for (IOFSwitchListener listener : switchListeners) {
+                                if (update.added)
+                                    listener.addedSwitch(update.sw);
+                                else
+                                    listener.removedSwitch(update.sw);
+                            }
+                        }
+                        break;
+                    case HA:
+                        if (log.isDebugEnabled()) {
+                            log.debug("Dispatching HA update newRole = {}, oldRole = {}",
+                                      update.newRole, update.oldRole);
+                        }
+                        if (haListeners != null) {
+                            for (IHARoleListener listener : haListeners) {
+                                    listener.roleChanged(update.oldRole, update.newRole);
+                            }
+                        }
+                        break;
+                    default:
+                        log.error("Unreognized update type " + update.type);
+                        break;
                 }
             } catch (InterruptedException e) {
                 return;
@@ -1602,7 +1628,8 @@ public class Controller implements IFloodlightProviderService {
                           e, StackTraceUtil.stackTraceToString(e));
                 return;
             } catch (Exception e) {
-                log.error("Exception in controller updates loop {} {}", e, StackTraceUtil.stackTraceToString(e));
+                log.error("Exception in controller updates loop {} {}", 
+                          e, StackTraceUtil.stackTraceToString(e));
             }
         }
     }
@@ -1632,6 +1659,11 @@ public class Controller implements IFloodlightProviderService {
             this.workerThreads = Integer.parseInt(threads);
         }
         log.info("Number of worker threads port set to {}", this.workerThreads);
+        String controllerId = configParams.get("controllerid");
+        if (controllerId != null) {
+            this.controllerId = controllerId;
+        }
+        log.info("ControllerId set to {}", this.controllerId);
     }
 
     private void initVendorMessages() {
@@ -1663,13 +1695,14 @@ public class Controller implements IFloodlightProviderService {
                                       ListenerDispatcher<OFType, 
                                                          IOFMessageListener>>();
         this.switchListeners = new CopyOnWriteArraySet<IOFSwitchListener>();
+        this.haListeners = new CopyOnWriteArraySet<IHARoleListener>();
         this.activeSwitches = new ConcurrentHashMap<Long, IOFSwitch>();
         this.connectedSwitches = new ConcurrentHashMap<Long, IOFSwitch>();
         this.updates = new LinkedBlockingQueue<Update>();
         this.factory = new BasicFactory();
         this.providerMap = new HashMap<String, List<IInfoProvider>>();
         setConfigParams(configParams);
-        this.setRole(getInitialRole());
+        this.role = getInitialRole(configParams.get("role"));
         initVendorMessages();
     }
     
@@ -1735,4 +1768,14 @@ public class Controller implements IFloodlightProviderService {
 		
 		return result;
 	}
+
+    @Override
+    public void addHAListener(IHARoleListener listener) {
+        this.haListeners.add(listener);
+    }
+
+    @Override
+    public void removeHAListener(IHARoleListener listener) {
+        this.haListeners.remove(listener);
+    }
 }
diff --git a/src/main/java/net/floodlightcontroller/core/web/RoleResource.java b/src/main/java/net/floodlightcontroller/core/web/RoleResource.java
index 45d170fbfbb0b0bbf1265d43a02da27b0d5de95c..d0bf2f837e62be1d4b915a1f23b60eb36e66d92d 100644
--- a/src/main/java/net/floodlightcontroller/core/web/RoleResource.java
+++ b/src/main/java/net/floodlightcontroller/core/web/RoleResource.java
@@ -61,6 +61,7 @@ public class RoleResource extends ServerResource {
         if (role == null) {
             log.warn ("Invalid role value specified in REST API to set controller role");
             setStatus(Status.CLIENT_ERROR_BAD_REQUEST, "Invalid role value");
+            return;
         }
         
         IFloodlightProviderService floodlightProvider = 
diff --git a/src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManager.java b/src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManager.java
index e37fc488d3a723ec890c84aa78a072440c5f2ea9..e8145f9762829a1d9fe692fdcd94617ddadc31bf 100644
--- a/src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManager.java
+++ b/src/main/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManager.java
@@ -41,6 +41,8 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
 
 import net.floodlightcontroller.core.FloodlightContext;
 import net.floodlightcontroller.core.IFloodlightProviderService;
+import net.floodlightcontroller.core.IFloodlightProviderService.Role;
+import net.floodlightcontroller.core.IHARoleListener;
 import net.floodlightcontroller.core.IInfoProvider;
 import net.floodlightcontroller.core.IOFMessageListener;
 import net.floodlightcontroller.core.IOFSwitch;
@@ -120,7 +122,7 @@ import org.slf4j.LoggerFactory;
 public class LinkDiscoveryManager
         implements IOFMessageListener, IOFSwitchListener, 
                    IStorageSourceListener, ILinkDiscoveryService,
-                   IFloodlightModule, IInfoProvider {
+                   IFloodlightModule, IInfoProvider, IHARoleListener {
     protected static Logger log = LoggerFactory.getLogger(LinkDiscoveryManager.class);
 
     // Names of table/fields for links in the storage API
@@ -184,11 +186,6 @@ public class LinkDiscoveryManager
     protected BlockingQueue<LDUpdate> updates;
     protected Thread updatesThread;
 
-    //This map provides the ids of broadcast domains connected to a switch cluster
-    protected Map<Long, Set<Long>> switchClusterBroadcastDomainMap;
-
-    protected boolean isTopologyValid = false;
-
     public int getLldpFrequency() {
         return lldpFrequency;
     }
@@ -1418,6 +1415,7 @@ public class LinkDiscoveryManager
         floodlightProvider.addOFMessageListener(OFType.PORT_STATUS, this);
         // Register for switch updates
         floodlightProvider.addOFSwitchListener(this);
+        floodlightProvider.addHAListener(this);
         floodlightProvider.addInfoProvider("summary", this);
         
         // init our rest api
@@ -1507,4 +1505,27 @@ public class LinkDiscoveryManager
 
         return info;
     }
+
+    // IHARoleListener
+    
+    @Override
+    public void roleChanged(Role oldRole, Role newRole) {
+        switch(newRole) {
+            case MASTER:
+                if (oldRole == Role.SLAVE) {
+                    log.debug("Sending LLDPs " +
+                            "to HA change from SLAVE->MASTER");
+                    sendLLDPs();
+                }
+                break;
+            case SLAVE:
+                log.debug("Clearing links due to " +
+                        "HA change to SLAVE");
+                switchLinks.clear();
+                links.clear();
+                portLinks.clear();
+                portBroadcastDomainLinks.clear();
+                break;
+        }
+    }
 }
diff --git a/src/main/java/net/floodlightcontroller/staticflowentry/StaticFlowEntryPusher.java b/src/main/java/net/floodlightcontroller/staticflowentry/StaticFlowEntryPusher.java
index 2be3de223b03e8975968a355854b6b122a002ff9..bff3a422fa9795bb15efb2892b0c15612adb3848 100644
--- a/src/main/java/net/floodlightcontroller/staticflowentry/StaticFlowEntryPusher.java
+++ b/src/main/java/net/floodlightcontroller/staticflowentry/StaticFlowEntryPusher.java
@@ -15,6 +15,8 @@ import java.util.concurrent.ConcurrentHashMap;
 
 import net.floodlightcontroller.core.FloodlightContext;
 import net.floodlightcontroller.core.IFloodlightProviderService;
+import net.floodlightcontroller.core.IFloodlightProviderService.Role;
+import net.floodlightcontroller.core.IHARoleListener;
 import net.floodlightcontroller.core.IOFMessageListener;
 import net.floodlightcontroller.core.IOFSwitch;
 import net.floodlightcontroller.core.IOFSwitchListener;
@@ -44,7 +46,7 @@ import org.slf4j.LoggerFactory;
 
 public class StaticFlowEntryPusher 
     implements IOFSwitchListener, IFloodlightModule, IStaticFlowEntryPusherService,
-        IStorageSourceListener, IOFMessageListener {
+        IStorageSourceListener, IOFMessageListener, IHARoleListener {
     protected static Logger log = LoggerFactory.getLogger(StaticFlowEntryPusher.class);
     public static final String StaticFlowName = "staticflowentry";
     
@@ -544,8 +546,9 @@ public class StaticFlowEntryPusher
     public void startUp(FloodlightModuleContext context) {        
         floodlightProvider.addOFMessageListener(OFType.FLOW_REMOVED, this);
         floodlightProvider.addOFSwitchListener(this);
-        // assumes no switches connected at startup()
+        floodlightProvider.addHAListener(this);
         
+        // assumes no switches connected at startup()
         storageSource.createTable(TABLE_NAME, null);
         storageSource.setTablePrimaryKeyName(TABLE_NAME, COLUMN_NAME);
         storageSource.addListener(TABLE_NAME, this);
@@ -601,4 +604,27 @@ public class StaticFlowEntryPusher
     public Map<String, OFFlowMod> getFlows(String dpid) {
         return entriesFromStorage.get(dpid);
     }
+
+    
+    // IHARoleListener
+    
+    @Override
+    public void roleChanged(Role oldRole, Role newRole) {
+        switch(newRole) {
+            case MASTER:
+                if (oldRole == Role.SLAVE) {
+                    log.debug("Re-reading static flows from storage due " +
+                            "to HA change from SLAVE->MASTER");
+                    entriesFromStorage = readEntriesFromStorage(); 
+                    entry2dpid = computeEntry2DpidMap(entriesFromStorage);
+                }
+                break;
+            case SLAVE:
+                log.debug("Clearing in-memory flows due to " +
+                        "HA change to SLAVE");
+                entry2dpid.clear();
+                entriesFromStorage.clear();
+                break;
+        }
+    }
 }
diff --git a/src/main/java/net/floodlightcontroller/topology/ITopologyService.java b/src/main/java/net/floodlightcontroller/topology/ITopologyService.java
index f2c95087d103ef44924e1a3f54acb01b9f9b4397..725c0d25ddba98a92bead784f5df7163970ec83e 100644
--- a/src/main/java/net/floodlightcontroller/topology/ITopologyService.java
+++ b/src/main/java/net/floodlightcontroller/topology/ITopologyService.java
@@ -15,6 +15,11 @@ public interface ITopologyService extends IFloodlightService  {
      */
     public boolean isInternal(long switchid, short port);
 
+    /**
+     * Returns the cluster ID of a given switch.
+     * @param switchId The DPID of the switch in long form
+     * @return The DPID of the switch that is the key for the cluster
+     */
     public long getSwitchClusterId(long switchId);
 
     /**
@@ -42,7 +47,7 @@ public interface ITopologyService extends IFloodlightService  {
      * islands could be different than clusters.
      * @param switch1
      * @param switch2
-     * @return
+     * @return True of they are in the same island, false otherwise
      */
     public boolean inSameIsland(long switch1, long switch2);
 
@@ -81,6 +86,11 @@ public interface ITopologyService extends IFloodlightService  {
 
     public boolean isInSameBroadcastDomain(long s1, short p1, long s2, short p2);
 
+    /**
+     * Gets a list of ports on a given switch
+     * @param sw The switch DPID in long
+     * @return The set of ports on this switch
+     */
     public Set<Short> getPorts(long sw);
 
     public Set<Short> getBroadcastPorts(long targetSw, long src, short srcPort);
diff --git a/src/main/java/net/floodlightcontroller/topology/TopologyManager.java b/src/main/java/net/floodlightcontroller/topology/TopologyManager.java
index 2ec736eb04325ff44d5b2c89bd0f800097fd206e..6dd7037d5aebba46ad05dad5603cff132982fdfd 100644
--- a/src/main/java/net/floodlightcontroller/topology/TopologyManager.java
+++ b/src/main/java/net/floodlightcontroller/topology/TopologyManager.java
@@ -11,6 +11,9 @@ import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.TimeUnit;
 
+import net.floodlightcontroller.core.IFloodlightProviderService;
+import net.floodlightcontroller.core.IFloodlightProviderService.Role;
+import net.floodlightcontroller.core.IHARoleListener;
 import net.floodlightcontroller.core.module.FloodlightModuleContext;
 import net.floodlightcontroller.core.module.FloodlightModuleException;
 import net.floodlightcontroller.core.module.IFloodlightModule;
@@ -36,8 +39,9 @@ import org.slf4j.LoggerFactory;
  *
  */
 
-public class TopologyManager implements IFloodlightModule, ITopologyService, 
-IRoutingService, ILinkDiscoveryListener {
+public class TopologyManager 
+    implements IFloodlightModule, ITopologyService, IRoutingService, 
+               ILinkDiscoveryListener, IHARoleListener {
 
     protected static Logger log = LoggerFactory.getLogger(TopologyManager.class);
 
@@ -45,9 +49,13 @@ IRoutingService, ILinkDiscoveryListener {
     protected Map<NodePortTuple, Set<Link>> switchPortLinks; // Set of links organized by node port tuple
     protected Map<NodePortTuple, Set<Link>> portBroadcastDomainLinks; // set of links that are broadcast domain links.
     protected Map<NodePortTuple, Set<Link>> tunnelLinks; // set of tunnel links
+    
+    // Dependencies
     protected ILinkDiscoveryService linkDiscovery;
-    protected ArrayList<ITopologyListener> topologyAware;
     protected IThreadPoolService threadPool;
+    protected IFloodlightProviderService floodlightProvider;
+    // Modules that listen to our updates
+    protected ArrayList<ITopologyListener> topologyAware;
 
     protected BlockingQueue<LDUpdate> ldUpdates;
     protected TopologyInstance currentInstance;
@@ -318,6 +326,7 @@ IRoutingService, ILinkDiscoveryListener {
                 new ArrayList<Class<? extends IFloodlightService>>();
         l.add(ILinkDiscoveryService.class);
         l.add(IThreadPoolService.class);
+        l.add(IFloodlightProviderService.class);
         return l;
     }
 
@@ -326,6 +335,7 @@ IRoutingService, ILinkDiscoveryListener {
             throws FloodlightModuleException {
         linkDiscovery = context.getServiceImpl(ILinkDiscoveryService.class);
         threadPool = context.getServiceImpl(IThreadPoolService.class);
+        floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class);
         
         switchPorts = new HashMap<Long,Set<Short>>();
         switchPortLinks = new HashMap<NodePortTuple, Set<Link>>();
@@ -333,7 +343,6 @@ IRoutingService, ILinkDiscoveryListener {
         tunnelLinks = new HashMap<NodePortTuple, Set<Link>>();
         topologyAware = new ArrayList<ITopologyListener>();
         ldUpdates = new LinkedBlockingQueue<LDUpdate>();
-        
     }
 
     @Override
@@ -341,6 +350,7 @@ IRoutingService, ILinkDiscoveryListener {
         ScheduledExecutorService ses = threadPool.getScheduledExecutor();
         newInstanceTask = new SingletonTask(ses, new NewInstanceWorker());
         linkDiscovery.addListener(this);
+        floodlightProvider.addHAListener(this);
         newInstanceTask.reschedule(1, TimeUnit.MILLISECONDS);
     }
 
@@ -459,5 +469,35 @@ IRoutingService, ILinkDiscoveryListener {
     public boolean inSameIsland(long switch1, long switch2) {
         return currentInstance.inSameIsland(switch1, switch2);
     }
+
+    /**
+     * Clears the current topology. Note that this does NOT
+     * send out updates.
+     */
+    public void clearCurrentTopology() {
+        switchPorts.clear();
+        switchPortLinks.clear();
+        portBroadcastDomainLinks.clear();
+        tunnelLinks.clear();
+        createNewInstance();
+    }
+
+    @Override
+    public void roleChanged(Role oldRole, Role newRole) {
+        switch(newRole) {
+            case MASTER:
+                if (oldRole == Role.SLAVE) {
+                    log.debug("Re-computing topology due " +
+                            "to HA change from SLAVE->MASTER");
+                    newInstanceTask.reschedule(1, TimeUnit.MILLISECONDS);
+                }
+                break;
+            case SLAVE:
+                log.debug("Clearing topology due to " +
+                        "HA change to SLAVE");
+                clearCurrentTopology();
+                break;
+        }
+    }
 }
 
diff --git a/src/main/java/net/floodlightcontroller/ui/web/StaticWebRoutable.java b/src/main/java/net/floodlightcontroller/ui/web/StaticWebRoutable.java
index 145418baaa35d4594ae5627d7c89679ff8aadb69..c1d5b5f471ba09c2252a2abc24737488bbe0d1fb 100644
--- a/src/main/java/net/floodlightcontroller/ui/web/StaticWebRoutable.java
+++ b/src/main/java/net/floodlightcontroller/ui/web/StaticWebRoutable.java
@@ -50,7 +50,7 @@ public class StaticWebRoutable implements RestletRoutable, IFloodlightModule {
     @Override
     public void startUp(FloodlightModuleContext context) {
         // Add our REST API
-        restApi.addRestletRoutable(new StaticWebRoutable());
+        restApi.addRestletRoutable(this);
         
     }
 
diff --git a/src/test/java/net/floodlightcontroller/core/test/MockFloodlightProvider.java b/src/test/java/net/floodlightcontroller/core/test/MockFloodlightProvider.java
index e903c5ea3f7e613c22648c7e005b416ab3bd27a8..56dc20fcba11f7448c5e8705cbad83c50ec77931 100644
--- a/src/test/java/net/floodlightcontroller/core/test/MockFloodlightProvider.java
+++ b/src/test/java/net/floodlightcontroller/core/test/MockFloodlightProvider.java
@@ -27,6 +27,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
 
 import net.floodlightcontroller.core.FloodlightContext;
 import net.floodlightcontroller.core.IFloodlightProviderService;
+import net.floodlightcontroller.core.IHARoleListener;
 import net.floodlightcontroller.core.IInfoProvider;
 import net.floodlightcontroller.core.IOFMessageListener;
 import net.floodlightcontroller.core.IOFSwitch;
@@ -51,6 +52,7 @@ import org.openflow.protocol.factory.BasicFactory;
 public class MockFloodlightProvider implements IFloodlightModule, IFloodlightProviderService {
     protected Map<OFType, List<IOFMessageListener>> listeners;
     protected List<IOFSwitchListener> switchListeners;
+    protected List<IHARoleListener> haListeners;
     protected Map<Long, IOFSwitch> switches;
     protected BasicFactory factory;
 
@@ -61,6 +63,7 @@ public class MockFloodlightProvider implements IFloodlightModule, IFloodlightPro
         listeners = new ConcurrentHashMap<OFType, List<IOFMessageListener>>();
         switches = new ConcurrentHashMap<Long, IOFSwitch>();
         switchListeners = new CopyOnWriteArrayList<IOFSwitchListener>();
+        haListeners = new CopyOnWriteArrayList<IHARoleListener>();
         factory = new BasicFactory();
     }
 
@@ -212,15 +215,6 @@ public class MockFloodlightProvider implements IFloodlightModule, IFloodlightPro
         // TODO Auto-generated method stub
         return null;
     }
-
-    @Override
-    public Role getRole() {
-        return null;
-    }
-    
-    @Override
-    public void setRole(Role role) {
-    }
     
     @Override
     public
@@ -254,4 +248,40 @@ public class MockFloodlightProvider implements IFloodlightModule, IFloodlightPro
 		// TODO Auto-generated method stub
 		return null;
 	}
+
+    @Override
+    public void addHAListener(IHARoleListener listener) {
+        haListeners.add(listener);
+    }
+
+    @Override
+    public void removeHAListener(IHARoleListener listener) {
+        haListeners.remove(listener);
+    }
+    
+    @Override
+    public Role getRole() {
+        return null;
+    }
+    
+    @Override
+    public void setRole(Role role) {
+        
+    }
+    
+    /**
+     * Dispatches a new role change notification
+     * @param oldRole
+     * @param newRole
+     */
+    public void dispatchRoleChanged(Role oldRole, Role newRole) {
+        for (IHARoleListener rl : haListeners) {
+            rl.roleChanged(oldRole, newRole);
+        }
+    }
+
+    @Override
+    public String getControllerId() {
+        return "localhost";
+    }
 }
diff --git a/src/test/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManagerTest.java b/src/test/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManagerTest.java
index c6521b93ae79aefc5d695483312033b8d2dda46d..fec23ee04999d32d44931fc4694bd2aa8bf2c1a3 100644
--- a/src/test/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManagerTest.java
+++ b/src/test/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManagerTest.java
@@ -29,6 +29,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import net.floodlightcontroller.core.IFloodlightProviderService;
+import net.floodlightcontroller.core.IFloodlightProviderService.Role;
 import net.floodlightcontroller.core.IOFSwitch;
 import net.floodlightcontroller.core.module.FloodlightModuleContext;
 import net.floodlightcontroller.core.test.MockThreadPoolService;
@@ -51,11 +52,25 @@ import net.floodlightcontroller.topology.TopologyManager;
  */
 public class LinkDiscoveryManagerTest extends FloodlightTestCase {
 
-    private LinkDiscoveryManager topology;
+    private TestLinkDiscoveryManager ldm;
     protected static Logger log = LoggerFactory.getLogger(LinkDiscoveryManagerTest.class);
     
+    public class TestLinkDiscoveryManager extends LinkDiscoveryManager {
+        public boolean isSendLLDPsCalled = false;
+        
+        @Override
+        protected void sendLLDPs() {
+            isSendLLDPsCalled = true;
+            super.sendLLDPs();
+        }
+        
+        public void reset() {
+            isSendLLDPsCalled = false;
+        }
+    }
+    
     public LinkDiscoveryManager getTopology() {
-        return topology;
+        return ldm;
     }
 
     public IOFSwitch createMockSwitch(Long id) {
@@ -68,22 +83,22 @@ public class LinkDiscoveryManagerTest extends FloodlightTestCase {
     public void setUp() throws Exception {
         super.setUp();
         FloodlightModuleContext cntx = new FloodlightModuleContext();
-        topology = new LinkDiscoveryManager();
+        ldm = new TestLinkDiscoveryManager();
         TopologyManager routingEngine = new TopologyManager();
-        topology.linkDiscoveryAware = new ArrayList<ILinkDiscoveryListener>();
+        ldm.linkDiscoveryAware = new ArrayList<ILinkDiscoveryListener>();
         MockThreadPoolService tp = new MockThreadPoolService();
         cntx.addService(IThreadPoolService.class, tp);
         cntx.addService(IRoutingService.class, routingEngine);
-        cntx.addService(ILinkDiscoveryService.class, topology);
-        cntx.addService(ITopologyService.class, topology);
+        cntx.addService(ILinkDiscoveryService.class, ldm);
+        cntx.addService(ITopologyService.class, ldm);
         cntx.addService(IStorageSourceService.class, new MemoryStorageSource());
         cntx.addService(IFloodlightProviderService.class, getMockFloodlightProvider());
         tp.init(cntx);
         routingEngine.init(cntx);
-        topology.init(cntx);
+        ldm.init(cntx);
         tp.startUp(cntx);
         routingEngine.startUp(cntx);
-        topology.startUp(cntx);
+        ldm.startUp(cntx);
     }
 
     @Test
@@ -216,8 +231,8 @@ public class LinkDiscoveryManagerTest extends FloodlightTestCase {
         LinkDiscoveryManager topology = getTopology();
         IOFSwitch sw1 = createMockSwitch(1L);
         IOFSwitch sw2 = createMockSwitch(2L);
-        //expect(topology.getSwitchClusterId(1L)).andReturn(1L).anyTimes();
-        //expect(topology.getSwitchClusterId(2L)).andReturn(1L).anyTimes();
+        //expect(ldm.getSwitchClusterId(1L)).andReturn(1L).anyTimes();
+        //expect(ldm.getSwitchClusterId(2L)).andReturn(1L).anyTimes();
         replay(sw1, sw2);
         LinkTuple lt = new LinkTuple(sw1, 1, sw2, 1);
         LinkInfo info;
@@ -329,4 +344,32 @@ public class LinkDiscoveryManagerTest extends FloodlightTestCase {
         assertTrue(topology.portBroadcastDomainLinks.get(lt.getDst()).contains(lt));
     }
 
+    @Test
+    public void testHARoleChange() throws Exception {
+        LinkDiscoveryManager topology = getTopology();
+        IOFSwitch sw1 = createMockSwitch(1L);
+        IOFSwitch sw2 = createMockSwitch(2L);
+        replay(sw1, sw2);
+        LinkTuple lt = new LinkTuple(sw1, 2, sw2, 1);
+        LinkInfo info = new LinkInfo(System.currentTimeMillis(), null,
+                                     0, 0);
+        topology.addOrUpdateLink(lt, info);
+
+        // check invariants hold
+        assertNotNull(topology.switchLinks.get(lt.getSrc().getSw()));
+        assertTrue(topology.switchLinks.get(lt.getSrc().getSw()).contains(lt));
+        assertNotNull(topology.portLinks.get(lt.getSrc()));
+        assertTrue(topology.portLinks.get(lt.getSrc()).contains(lt));
+        assertNotNull(topology.portLinks.get(lt.getDst()));
+        assertTrue(topology.portLinks.get(lt.getDst()).contains(lt));
+        assertTrue(topology.links.containsKey(lt));
+        
+        // check that it clears from memory
+        getMockFloodlightProvider().dispatchRoleChanged(null, Role.SLAVE);
+        assertTrue(topology.switchLinks.isEmpty());
+        getMockFloodlightProvider().dispatchRoleChanged(Role.SLAVE, Role.MASTER);
+        // check that lldps were sent
+        assertTrue(ldm.isSendLLDPsCalled);
+        ldm.reset();
+    }
 }
diff --git a/src/test/java/net/floodlightcontroller/staticflowentry/StaticFlowTests.java b/src/test/java/net/floodlightcontroller/staticflowentry/StaticFlowTests.java
index 9227eff8f581f2e2910836ce97ee9f40a2fd677b..186fd69699f1a4490fedd4f4a73569cd46b93fed 100644
--- a/src/test/java/net/floodlightcontroller/staticflowentry/StaticFlowTests.java
+++ b/src/test/java/net/floodlightcontroller/staticflowentry/StaticFlowTests.java
@@ -22,6 +22,7 @@ import org.openflow.util.HexString;
 
 
 import net.floodlightcontroller.core.FloodlightContext;
+import net.floodlightcontroller.core.IFloodlightProviderService.Role;
 import net.floodlightcontroller.core.IOFSwitch;
 import net.floodlightcontroller.core.module.FloodlightModuleContext;
 import net.floodlightcontroller.core.module.FloodlightModuleException;
@@ -293,4 +294,41 @@ public class StaticFlowTests extends FloodlightTestCase {
 
         return storage;
     }
+    
+    @Test 
+    public void testHARoleChanged() throws IOException {
+        StaticFlowEntryPusher staticFlowEntryPusher = new StaticFlowEntryPusher();
+        IStorageSourceService storage = createStorageWithFlowEntries();
+        MockFloodlightProvider mfp = getMockFloodlightProvider();
+        staticFlowEntryPusher.setFloodlightProvider(mfp);
+        staticFlowEntryPusher.setStorageSource(storage);
+        RestApiServer restApi = new RestApiServer();
+        try {
+            FloodlightModuleContext fmc = new FloodlightModuleContext();
+            restApi.init(fmc);
+        } catch (FloodlightModuleException e) {
+            e.printStackTrace();
+        }
+        staticFlowEntryPusher.restApi = restApi;
+        staticFlowEntryPusher.startUp(null);    // again, to hack unittest
+        
+        assert(staticFlowEntryPusher.entry2dpid.containsValue(TestSwitch1DPID));
+        assert(staticFlowEntryPusher.entriesFromStorage.containsValue(FlowMod1));
+        assert(staticFlowEntryPusher.entriesFromStorage.containsValue(FlowMod2));
+        assert(staticFlowEntryPusher.entriesFromStorage.containsValue(FlowMod3));
+        
+        // Send a notification that we've changed to slave
+        mfp.dispatchRoleChanged(null, Role.SLAVE);
+        // Make sure we've removed all our entries
+        assert(staticFlowEntryPusher.entry2dpid.isEmpty());
+        assert(staticFlowEntryPusher.entriesFromStorage.isEmpty());
+        
+        // Send a notification that we've changed to master
+        mfp.dispatchRoleChanged(Role.SLAVE, Role.MASTER);  
+        // Make sure we've learned the entries
+        assert(staticFlowEntryPusher.entry2dpid.containsValue(TestSwitch1DPID));
+        assert(staticFlowEntryPusher.entriesFromStorage.containsValue(FlowMod1));
+        assert(staticFlowEntryPusher.entriesFromStorage.containsValue(FlowMod2));
+        assert(staticFlowEntryPusher.entriesFromStorage.containsValue(FlowMod3));
+    }
 }
diff --git a/src/test/java/net/floodlightcontroller/test/FloodlightTestCase.java b/src/test/java/net/floodlightcontroller/test/FloodlightTestCase.java
index ac711dbd3837d2109c45905761798df975cef2e1..7b81d42178845c944bc9932779b344c18330b9a4 100644
--- a/src/test/java/net/floodlightcontroller/test/FloodlightTestCase.java
+++ b/src/test/java/net/floodlightcontroller/test/FloodlightTestCase.java
@@ -23,6 +23,7 @@ import net.floodlightcontroller.core.IFloodlightProviderService;
 import net.floodlightcontroller.core.test.MockFloodlightProvider;
 import net.floodlightcontroller.packet.Ethernet;
 
+import org.junit.Test;
 import org.openflow.protocol.OFMessage;
 import org.openflow.protocol.OFPacketIn;
 import org.openflow.protocol.OFType;
@@ -65,11 +66,8 @@ public class FloodlightTestCase extends TestCase {
     public void setUp() throws Exception {
         mockFloodlightProvider = new MockFloodlightProvider();
     }
- 
-    /**
-     * @return the applicationContext
-     */
 
+    @Test
     public void testSanity() {
         assertTrue(true);
     }
diff --git a/src/test/java/net/floodlightcontroller/topology/TopologyManagerTest.java b/src/test/java/net/floodlightcontroller/topology/TopologyManagerTest.java
index 816eadea8ec7ba08b85c0f2ce5c401d7385cf04e..bcc886a42f1670371032d6e9e79e521ea838c4ec 100644
--- a/src/test/java/net/floodlightcontroller/topology/TopologyManagerTest.java
+++ b/src/test/java/net/floodlightcontroller/topology/TopologyManagerTest.java
@@ -1,11 +1,11 @@
 package net.floodlightcontroller.topology;
 
-import static org.junit.Assert.*;
 import net.floodlightcontroller.core.IFloodlightProviderService;
+import net.floodlightcontroller.core.IFloodlightProviderService.Role;
 import net.floodlightcontroller.core.module.FloodlightModuleContext;
-import net.floodlightcontroller.core.test.MockFloodlightProvider;
 import net.floodlightcontroller.core.test.MockThreadPoolService;
 import net.floodlightcontroller.linkdiscovery.ILinkDiscovery;
+import net.floodlightcontroller.test.FloodlightTestCase;
 import net.floodlightcontroller.threadpool.IThreadPoolService;
 import net.floodlightcontroller.topology.TopologyManager;
 
@@ -14,32 +14,26 @@ import org.junit.Test;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class TopologyManagerTest {
+public class TopologyManagerTest extends FloodlightTestCase {
     protected static Logger log = LoggerFactory.getLogger(TopologyManagerTest.class);
-    TopologyManager topologyManager;
+    TopologyManager tm;
     FloodlightModuleContext fmc;
-    protected MockFloodlightProvider mockFloodlightProvider;
     
-    @Before 
-    public void SetUp() throws Exception {
-        mockFloodlightProvider = new MockFloodlightProvider();
+    @Before
+    public void setUp() throws Exception {
+        super.setUp();
         fmc = new FloodlightModuleContext();
-        fmc.addService(IFloodlightProviderService.class, mockFloodlightProvider);
+        fmc.addService(IFloodlightProviderService.class, getMockFloodlightProvider());
         MockThreadPoolService tp = new MockThreadPoolService();
         fmc.addService(IThreadPoolService.class, tp);
-        topologyManager  = new TopologyManager();
+        tm  = new TopologyManager();
         tp.init(fmc);
-        topologyManager.init(fmc);
+        tm.init(fmc);
         tp.startUp(fmc);
     }
 
-    public TopologyManager getTopologyManager() {
-        return topologyManager;
-    }
-
     @Test
-    public void basicTest1() {
-        TopologyManager tm = getTopologyManager();
+    public void testBasic1() throws Exception {
         tm.addOrUpdateLink((long)1, (short)1, (long)2, (short)1, ILinkDiscovery.LinkType.DIRECT_LINK);
         assertTrue(tm.getSwitchPorts().size() == 2);  // for two nodes.
         assertTrue(tm.getSwitchPorts().get((long)1).size()==1);
@@ -89,8 +83,7 @@ public class TopologyManagerTest {
     }
 
     @Test
-    public void basicTest2() {
-        TopologyManager tm = getTopologyManager();
+    public void testBasic2() throws Exception {
         tm.addOrUpdateLink((long)1, (short)1, (long)2, (short)1, ILinkDiscovery.LinkType.DIRECT_LINK);
         tm.addOrUpdateLink((long)2, (short)2, (long)3, (short)1, ILinkDiscovery.LinkType.MULTIHOP_LINK);
         tm.addOrUpdateLink((long)3, (short)2, (long)1, (short)2, ILinkDiscovery.LinkType.TUNNEL);
@@ -136,4 +129,14 @@ public class TopologyManagerTest {
         assertTrue(tm.getPortBroadcastDomainLinks().size()==0);
         assertTrue(tm.getTunnelLinks().size()==0);
     }
+    
+    @Test
+    public void testHARoleChange() throws Exception {
+        testBasic2();
+        getMockFloodlightProvider().dispatchRoleChanged(null, Role.SLAVE);
+        assert(tm.switchPorts.isEmpty());
+        assert(tm.switchPortLinks.isEmpty());
+        assert(tm.portBroadcastDomainLinks.isEmpty());
+        assert(tm.tunnelLinks.isEmpty());
+    }
 }