Bug 1029: Remove dead code: samples/clustersession
[controller.git] / opendaylight / hosttracker_new / implementation / src / main / java / org / opendaylight / controller / hosttracker / internal / DeviceManagerImpl.java
index 8435a94f5836c28db029001574b37b076f575163..ee75ac06e34ea74921b8fb6ee6af75dc24fb31ec 100755 (executable)
@@ -37,6 +37,8 @@ import static org.opendaylight.controller.hosttracker.internal.DeviceManagerImpl
 import static org.opendaylight.controller.hosttracker.internal.DeviceManagerImpl.DeviceUpdate.Change.CHANGE;
 import static org.opendaylight.controller.hosttracker.internal.DeviceManagerImpl.DeviceUpdate.Change.DELETE;
 
+import java.net.InetAddress;
+import java.net.UnknownHostException;
 import java.util.ArrayList;
 import java.util.Calendar;
 import java.util.Collection;
@@ -50,10 +52,12 @@ import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.Queue;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.TimeUnit;
 
@@ -64,10 +68,20 @@ import org.opendaylight.controller.hosttracker.IDeviceService;
 import org.opendaylight.controller.hosttracker.IEntityClass;
 import org.opendaylight.controller.hosttracker.IEntityClassListener;
 import org.opendaylight.controller.hosttracker.IEntityClassifierService;
+import org.opendaylight.controller.hosttracker.IfIptoHost;
+import org.opendaylight.controller.hosttracker.IfNewHostNotify;
 import org.opendaylight.controller.hosttracker.SwitchPort;
+import org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector;
+import org.opendaylight.controller.sal.core.ConstructionException;
 import org.opendaylight.controller.sal.core.Edge;
+import org.opendaylight.controller.sal.core.Host;
+import org.opendaylight.controller.sal.core.Node;
 import org.opendaylight.controller.sal.core.NodeConnector;
 import org.opendaylight.controller.sal.core.NodeConnector.NodeConnectorIDType;
+import org.opendaylight.controller.sal.core.Property;
+import org.opendaylight.controller.sal.core.State;
+import org.opendaylight.controller.sal.core.Tier;
+import org.opendaylight.controller.sal.core.UpdateType;
 import org.opendaylight.controller.sal.packet.ARP;
 import org.opendaylight.controller.sal.packet.Ethernet;
 import org.opendaylight.controller.sal.packet.IDataPacketService;
@@ -75,10 +89,17 @@ import org.opendaylight.controller.sal.packet.IListenDataPacket;
 import org.opendaylight.controller.sal.packet.Packet;
 import org.opendaylight.controller.sal.packet.PacketResult;
 import org.opendaylight.controller.sal.packet.RawPacket;
+import org.opendaylight.controller.sal.packet.address.DataLinkAddress;
+import org.opendaylight.controller.sal.packet.address.EthernetAddress;
 import org.opendaylight.controller.sal.topology.TopoEdgeUpdate;
+import org.opendaylight.controller.sal.utils.HexEncode;
 import org.opendaylight.controller.sal.utils.ListenerDispatcher;
 import org.opendaylight.controller.sal.utils.MultiIterator;
+import org.opendaylight.controller.sal.utils.NetUtils;
 import org.opendaylight.controller.sal.utils.SingletonTask;
+import org.opendaylight.controller.sal.utils.Status;
+import org.opendaylight.controller.sal.utils.StatusCode;
+import org.opendaylight.controller.switchmanager.IInventoryListener;
 import org.opendaylight.controller.switchmanager.ISwitchManager;
 import org.opendaylight.controller.topologymanager.ITopologyManager;
 import org.opendaylight.controller.topologymanager.ITopologyManagerAware;
@@ -93,23 +114,13 @@ import org.slf4j.LoggerFactory;
  * @author readams
  */
 public class DeviceManagerImpl implements IDeviceService, IEntityClassListener,
-        IListenDataPacket, ITopologyManagerAware {
+        IListenDataPacket, ITopologyManagerAware, IfIptoHost,
+        IInventoryListener {
     protected static Logger logger = LoggerFactory
             .getLogger(DeviceManagerImpl.class);
 
     public static final String MODULE_NAME = "devicemanager";
 
-    // protected ITopologyService topology;
-    // protected IStorageSourceService storageSource;
-    // protected IRestApiService restApi;
-    // protected IThreadPoolService threadPool;
-    // protected IFlowReconcileService flowReconcileMgr;
-    // protected IFlowReconcileEngineService flowReconcileEngine;
-    // protected IDebugCounterService debugCounters;
-    // private ISyncService syncService;
-    // private IStoreClient<String,DeviceSyncRepresentation> storeClient;
-    // private DeviceSyncManager deviceSyncManager;
-
     private ITopologyManager topology;
     private ISwitchManager switchManager = null;
     private IDataPacketService dataPacketService = null;
@@ -164,30 +175,6 @@ public class DeviceManagerImpl implements IDeviceService, IEntityClassListener,
     static final String DEVICE_SYNC_STORE_NAME = DeviceManagerImpl.class
             .getCanonicalName() + ".stateStore";
 
-    /**
-     * Time interval between writes of entries for the same device to the sync
-     * store.
-     */
-    // static final int DEFAULT_SYNC_STORE_WRITE_INTERVAL_MS =
-    // 5*60*1000; // 5 min
-    // private int syncStoreWriteIntervalMs =
-    // DEFAULT_SYNC_STORE_WRITE_INTERVAL_MS;
-
-    /**
-     * Time after SLAVE->MASTER until we run the consolidate store code.
-     */
-    // static final int DEFAULT_INITIAL_SYNC_STORE_CONSOLIDATE_MS =
-    // 15*1000; // 15 sec
-    // private int initialSyncStoreConsolidateMs =
-    // DEFAULT_INITIAL_SYNC_STORE_CONSOLIDATE_MS;
-
-    /**
-     * Time interval between consolidate store runs.
-     */
-    // static final int DEFAULT_SYNC_STORE_CONSOLIDATE_INTERVAL_MS =
-    // 75*60*1000; // 75 min
-    // private final int syncStoreConsolidateIntervalMs =
-    // DEFAULT_SYNC_STORE_CONSOLIDATE_INTERVAL_MS;
 
     /**
      * Time in milliseconds before entities will expire
@@ -205,6 +192,7 @@ public class DeviceManagerImpl implements IDeviceService, IEntityClassListener,
      */
     protected ConcurrentHashMap<Long, Device> deviceMap;
 
+    protected ConcurrentHashMap<NodeConnector, Entity> inactiveStaticDevices;
     /**
      * Counter used to generate device keys
      */
@@ -285,6 +273,12 @@ public class DeviceManagerImpl implements IDeviceService, IEntityClassListener,
      */
     protected ListenerDispatcher<String, IDeviceListener> deviceListeners;
 
+    /**
+     * Using the IfNewHostNotify to notify listeners of host changes.
+     */
+    private Set<IfNewHostNotify> newHostNotify = Collections
+            .synchronizedSet(new HashSet<IfNewHostNotify>());
+
     /**
      * A device update event to be dispatched
      */
@@ -356,11 +350,11 @@ public class DeviceManagerImpl implements IDeviceService, IEntityClassListener,
             long newDomain = 0;
             boolean newBD = false;
 
-            if (oldDomain < newDomain)
-                return -1;
-            else if (oldDomain > newDomain)
+            if (oldDomain < newDomain) {
+               return -1;
+            } else if (oldDomain > newDomain) {
                 return 1;
-
+            }
             // Give preference to OFPP_LOCAL always
             if (!oldAP.getPort().getType().equals(NodeConnectorIDType.SWSTACK)
                     && newAP.getPort().getType()
@@ -380,8 +374,7 @@ public class DeviceManagerImpl implements IDeviceService, IEntityClassListener,
                 return -compare(newAP, oldAP);
 
             long activeOffset = 0;
-            // XXX - missing functionality -- need topology
-            // if (!topology.isConsistent(oldSw, oldPort, newSw, newPort)) {
+
             if (!newBD && oldBD) {
                 return -1;
             }
@@ -391,10 +384,6 @@ public class DeviceManagerImpl implements IDeviceService, IEntityClassListener,
                 activeOffset = AttachmentPoint.OPENFLOW_TO_EXTERNAL_TIMEOUT;
             }
 
-            // } else {
-            // // The attachment point is consistent.
-            // activeOffset = AttachmentPoint.CONSISTENT_TIMEOUT;
-            // }
 
             if ((newAP.getActiveSince() > oldAP.getLastSeen() + activeOffset)
                     || (newAP.getLastSeen() > oldAP.getLastSeen()
@@ -424,6 +413,14 @@ public class DeviceManagerImpl implements IDeviceService, IEntityClassListener,
     // Dependency injection
     // ********************
 
+    void setNewHostNotify(IfNewHostNotify obj) {
+        this.newHostNotify.add(obj);
+    }
+
+    void unsetNewHostNotify(IfNewHostNotify obj) {
+        this.newHostNotify.remove(obj);
+    }
+
     void setDataPacketService(IDataPacketService s) {
         this.dataPacketService = s;
     }
@@ -467,18 +464,12 @@ public class DeviceManagerImpl implements IDeviceService, IEntityClassListener,
         secondaryIndexMap = new HashMap<EnumSet<DeviceField>, DeviceIndex>();
 
         deviceMap = new ConcurrentHashMap<Long, Device>();
+        inactiveStaticDevices = new ConcurrentHashMap<NodeConnector, Entity>();
         classStateMap = new ConcurrentHashMap<String, ClassState>();
         apComparator = new AttachmentPointComparator();
 
         addIndex(true, EnumSet.of(DeviceField.IPV4));
 
-        // floodlightProvider.addOFMessageListener(OFType.PACKET_IN, this);
-        // floodlightProvider.addHAListener(this.haListenerDelegate);
-        // if (topology != null)
-        // topology.addListener(this);
-        // flowReconcileMgr.addFlowReconcileListener(this);
-        // entityClassifier.addListener(this);
-
         stopped = false;
         // XXX - Should use a common threadpool but this doesn't currently exist
         ses = Executors.newScheduledThreadPool(1);
@@ -494,33 +485,7 @@ public class DeviceManagerImpl implements IDeviceService, IEntityClassListener,
         entityCleanupTask = new SingletonTask(ses, ecr);
         entityCleanupTask.reschedule(ENTITY_CLEANUP_INTERVAL, TimeUnit.SECONDS);
 
-        /*
-         * XXX Missing functionality if (restApi != null) {
-         * restApi.addRestletRoutable(new DeviceRoutable()); } else {
-         * logger.debug("Could not instantiate REST API"); }
-         */
-
         registerDeviceManagerDebugCounters();
-
-        /*
-         * XXX Missing functionality try {
-         * this.syncService.registerStore(DEVICE_SYNC_STORE_NAME, Scope.LOCAL);
-         * this.storeClient = this.syncService
-         * .getStoreClient(DEVICE_SYNC_STORE_NAME, String.class,
-         * DeviceSyncRepresentation.class); } catch (SyncException e) { throw
-         * new FloodlightModuleException("Error while setting up sync service",
-         * e); }
-         *
-         * Runnable consolidateStoreRunner = new Runnable() {
-         *
-         * @Override public void run() { deviceSyncManager.consolidateStore();
-         * storeConsolidateTask.reschedule(syncStoreConsolidateIntervalMs,
-         * TimeUnit.MILLISECONDS); debugCounters.flushCounters(); } };
-         * storeConsolidateTask = new SingletonTask(ses,
-         * consolidateStoreRunner); if (isMaster)
-         * storeConsolidateTask.reschedule(syncStoreConsolidateIntervalMs,
-         * TimeUnit.MILLISECONDS);
-         */
     }
 
     /**
@@ -534,6 +499,18 @@ public class DeviceManagerImpl implements IDeviceService, IEntityClassListener,
     // IDeviceManagerService
     // *********************
 
+    void setSwitchManager(ISwitchManager s) {
+        logger.debug("SwitchManager set");
+        this.switchManager = s;
+    }
+
+    void unsetSwitchManager(ISwitchManager s) {
+        if (this.switchManager == s) {
+            logger.debug("SwitchManager removed!");
+            this.switchManager = null;
+        }
+    }
+
     @Override
     public IDevice getDevice(Long deviceKey) {
         return deviceMap.get(deviceKey);
@@ -709,49 +686,6 @@ public class DeviceManagerImpl implements IDeviceService, IEntityClassListener,
         }
     }
 
-    // ***************
-    // IFlowReconcileListener
-    // ***************
-    /*
-     * XXX - Missing functionality
-     *
-     * @Override public Command reconcileFlows(ArrayList<OFMatchReconcile>
-     * ofmRcList) { ListIterator<OFMatchReconcile> iter =
-     * ofmRcList.listIterator(); while (iter.hasNext()) { OFMatchReconcile ofm =
-     * iter.next();
-     *
-     * // Remove the STOPPed flow. if (Command.STOP == reconcileFlow(ofm)) {
-     * iter.remove(); } }
-     *
-     * if (ofmRcList.size() > 0) { return Command.CONTINUE; } else { return
-     * Command.STOP; } }
-     *
-     * protected Command reconcileFlow(OFMatchReconcile ofm) {
-     * debugCounters.updateCounter(CNT_RECONCILE_REQUEST); // Extract source
-     * entity information Entity srcEntity =
-     * getEntityFromFlowMod(ofm.ofmWithSwDpid, true); if (srcEntity == null) {
-     * debugCounters.updateCounter(CNT_RECONCILE_NO_SOURCE); return
-     * Command.STOP; }
-     *
-     * // Find the device by source entity Device srcDevice =
-     * findDeviceByEntity(srcEntity); if (srcDevice == null) {
-     * debugCounters.updateCounter(CNT_RECONCILE_NO_SOURCE); return
-     * Command.STOP; } // Store the source device in the context
-     * fcStore.put(ofm.cntx, CONTEXT_SRC_DEVICE, srcDevice);
-     *
-     * // Find the device matching the destination from the entity // classes of
-     * the source. Entity dstEntity = getEntityFromFlowMod(ofm.ofmWithSwDpid,
-     * false); Device dstDevice = null; if (dstEntity != null) { dstDevice =
-     * findDestByEntity(srcDevice.getEntityClass(), dstEntity); if (dstDevice !=
-     * null) fcStore.put(ofm.cntx, CONTEXT_DST_DEVICE, dstDevice); else
-     * debugCounters.updateCounter(CNT_RECONCILE_NO_DEST); } else {
-     * debugCounters.updateCounter(CNT_RECONCILE_NO_DEST); } if
-     * (logger.isTraceEnabled()) {
-     * logger.trace("Reconciling flow: match={}, srcEntity={}, srcDev={}, " +
-     * "dstEntity={}, dstDev={}", new Object[] {ofm.ofmWithSwDpid.getOfMatch(),
-     * srcEntity, srcDevice, dstEntity, dstDevice } ); } return
-     * Command.CONTINUE; }
-     */
 
     // *****************
     // IListenDataPacket
@@ -763,11 +697,6 @@ public class DeviceManagerImpl implements IDeviceService, IEntityClassListener,
         if (inPkt == null) {
             return PacketResult.IGNORED;
         }
-        try {
-            throw new Exception("Sample");
-        } catch (Exception e) {
-            logger.error("Sample stack trace", e);
-        }
 
         Packet formattedPak = this.dataPacketService.decodeDataPacket(inPkt);
         Ethernet eth;
@@ -781,7 +710,6 @@ public class DeviceManagerImpl implements IDeviceService, IEntityClassListener,
         NodeConnector inPort = inPkt.getIncomingNodeConnector();
         Entity srcEntity = getSourceEntityFromPacket(eth, inPort);
         if (srcEntity == null) {
-            // debugCounters.updateCounter(CNT_BROADCAST_SOURCE);
             return PacketResult.CONSUME;
         }
 
@@ -796,38 +724,10 @@ public class DeviceManagerImpl implements IDeviceService, IEntityClassListener,
         // Learn/lookup device information
         Device srcDevice = learnDeviceByEntity(srcEntity);
         if (srcDevice == null) {
-            // debugCounters.updateCounter(CNT_NO_SOURCE);
             return PacketResult.CONSUME;
         }
         logger.trace("Saw packet from device {}", srcDevice);
 
-        // // Store the source device in the context
-        // fcStore.put(cntx, CONTEXT_SRC_DEVICE, srcDevice);
-        //
-        // // Find the device matching the destination from the entity
-        // // classes of the source.
-        // Entity dstEntity = getDestEntityFromPacket(eth);
-        // Device dstDevice = null;
-        // if (dstEntity != null) {
-        // dstDevice =
-        // findDestByEntity(srcDevice.getEntityClass(), dstEntity);
-        // if (dstDevice != null)
-        // fcStore.put(cntx, CONTEXT_DST_DEVICE, dstDevice);
-        // //else
-        // //debugCounters.updateCounter(CNT_NO_DEST);
-        // } else {
-        // //debugCounters.updateCounter(CNT_NO_DEST);
-        // }
-        //
-        // if (logger.isTraceEnabled()) {
-        // logger.trace("Received PI: {} on switch {}, port {} *** eth={}" +
-        // " *** srcDev={} *** dstDev={} *** ",
-        // new Object[] { pi, sw.getStringId(), pi.getInPort(), eth,
-        // srcDevice, dstDevice });
-        // }
-        //
-        // snoopDHCPClientName(eth, srcDevice);
-
         return PacketResult.KEEP_PROCESSING;
     }
 
@@ -835,32 +735,6 @@ public class DeviceManagerImpl implements IDeviceService, IEntityClassListener,
     // Internal methods
     // ****************
 
-    /**
-     * Snoop and record client-provided host name from DHCP requests
-     *
-     * @param eth
-     * @param srcDevice
-     */
-    // private void snoopDHCPClientName(Ethernet eth, Device srcDevice) {
-    // if (! (eth.getPayload() instanceof IPv4) )
-    // return;
-    // IPv4 ipv4 = (IPv4) eth.getPayload();
-    // if (! (ipv4.getPayload() instanceof UDP) )
-    // return;
-    // UDP udp = (UDP) ipv4.getPayload();
-    // if (!(udp.getPayload() instanceof DHCP))
-    // return;
-    // DHCP dhcp = (DHCP) udp.getPayload();
-    // byte opcode = dhcp.getOpCode();
-    // if (opcode == DHCP.OPCODE_REQUEST) {
-    // DHCPOption dhcpOption = dhcp.getOption(
-    // DHCPOptionCode.OptionCode_Hostname);
-    // if (dhcpOption != null) {
-    // debugCounters.updateCounter(CNT_DHCP_CLIENT_NAME_SNOOPED);
-    // srcDevice.dhcpClientName = new String(dhcpOption.getData());
-    // }
-    // }
-    // }
 
     /**
      * Check whether the given attachment point is valid given the current
@@ -963,90 +837,6 @@ public class DeviceManagerImpl implements IDeviceService, IEntityClassListener,
         learnDeviceByEntity(e);
     }
 
-    /**
-     * Get a (partial) entity for the destination from the packet.
-     *
-     * @param eth
-     * @return
-     */
-    // protected Entity getDestEntityFromPacket(Ethernet eth) {
-    // byte[] dlAddrArr = eth.getDestinationMACAddress();
-    // long dlAddr = Ethernet.toLong(dlAddrArr);
-    // short vlan = eth.getVlanID();
-    // int nwDst = 0;
-    //
-    // // Ignore broadcast/multicast destination
-    // if ((dlAddrArr[0] & 0x1) != 0)
-    // return null;
-    //
-    // if (eth.getPayload() instanceof IPv4) {
-    // IPv4 ipv4 = (IPv4) eth.getPayload();
-    // nwDst = ipv4.getDestinationAddress();
-    // }
-    //
-    // return new Entity(dlAddr,
-    // ((vlan >= 0) ? vlan : null),
-    // ((nwDst != 0) ? nwDst : null),
-    // null,
-    // null,
-    // null);
-    // }
-
-    /**
-     * Parse an entity from an OFMatchWithSwDpid.
-     *
-     * @param ofmWithSwDpid
-     * @return the entity from the packet
-     */
-    // private Entity getEntityFromFlowMod(OFMatchWithSwDpid ofmWithSwDpid,
-    // boolean isSource) {
-    // byte[] dlAddrArr = ofmWithSwDpid.getOfMatch().getDataLayerSource();
-    // int nwSrc = ofmWithSwDpid.getOfMatch().getNetworkSource();
-    // if (!isSource) {
-    // dlAddrArr = ofmWithSwDpid.getOfMatch().getDataLayerDestination();
-    // nwSrc = ofmWithSwDpid.getOfMatch().getNetworkDestination();
-    // }
-    //
-    // long dlAddr = Ethernet.toLong(dlAddrArr);
-    //
-    // // Ignore broadcast/multicast source
-    // if ((dlAddrArr[0] & 0x1) != 0)
-    // return null;
-    //
-    // Long swDpid = null;
-    // Short inPort = null;
-    //
-    // if (isSource) {
-    // swDpid = ofmWithSwDpid.getSwitchDataPathId();
-    // inPort = ofmWithSwDpid.getOfMatch().getInputPort();
-    // }
-    //
-    // /**for the new flow cache design, the flow mods retrived are not always
-    // from the source, learn AP should be disabled --meiyang*/
-    // boolean learnap = false;
-    // /**
-    // * if (swDpid == null ||
-    // inPort == null ||
-    // !isValidAttachmentPoint(swDpid, inPort)) {
-    // // If this is an internal port or we otherwise don't want
-    // // to learn on these ports. In the future, we should
-    // // handle this case by labeling flows with something that
-    // // will give us the entity class. For now, we'll do our
-    // // best assuming attachment point information isn't used
-    // // as a key field.
-    // learnap = false;
-    // }
-    // */
-    //
-    // short vlan = ofmWithSwDpid.getOfMatch().getDataLayerVirtualLan();
-    // return new Entity(dlAddr,
-    // ((vlan >= 0) ? vlan : null),
-    // ((nwSrc != 0) ? nwSrc : null),
-    // (learnap ? swDpid : null),
-    // (learnap ? (int)inPort : null),
-    // new Date());
-    // }
-
     /**
      * Look up a {@link Device} based on the provided {@link Entity}. We first
      * check the primary index. If we do not find an entry there we classify the
@@ -1149,6 +939,7 @@ public class DeviceManagerImpl implements IDeviceService, IEntityClassListener,
         logger.info("Primary index {}", primaryIndex);
         ArrayList<Long> deleteQueue = null;
         LinkedList<DeviceUpdate> deviceUpdates = null;
+        Device oldDevice = null;
         Device device = null;
 
         // we may need to restart the learning process if we detect
@@ -1304,7 +1095,7 @@ public class DeviceManagerImpl implements IDeviceService, IEntityClassListener,
                 // modified this Device).
                 if (!res)
                     continue;
-
+                oldDevice = device;
                 device = newDevice;
                 // update indices
                 if (!updateIndices(device, deviceKey)) {
@@ -1333,7 +1124,7 @@ public class DeviceManagerImpl implements IDeviceService, IEntityClassListener,
                 if (moved) {
                     // we count device moved events in
                     // sendDeviceMovedNotification()
-                    sendDeviceMovedNotification(device);
+                    sendDeviceMovedNotification(device, oldDevice);
                     if (logger.isTraceEnabled()) {
                         logger.trace("Device moved: attachment points {},"
                                 + "entities {}", device.attachmentPoints,
@@ -1427,9 +1218,74 @@ public class DeviceManagerImpl implements IDeviceService, IEntityClassListener,
 
     protected void notifyListeners(List<IDeviceListener> listeners,
             DeviceUpdate update) {
-        if (listeners == null) {
+        // Topology update is for some reason outside of listeners registry
+        // logic
+        Entity[] ents = update.device.getEntities();
+        Entity e = ents[ents.length - 1];
+
+        NodeConnector p = e.getPort();
+        Node node = p.getNode();
+        Host h = null;
+        try {
+
+            byte[] mac = NetUtils.longToByteArray6(e.getMacAddress());
+            DataLinkAddress dla = new EthernetAddress(
+                    mac);
+            e.getIpv4Address();
+            InetAddress.getAllByName(e.getIpv4Address().toString());
+            h = new org.opendaylight.controller.sal.core.Host(dla,
+                    InetAddress.getByName(e.getIpv4Address().toString()));
+        } catch (ConstructionException ce) {
+            p = null;
+            h = null;
+        } catch (UnknownHostException ue) {
+            p = null;
+            h = null;
+        }
+
+        if (topology != null && p != null && h != null) {
+            if (update.change.equals(DeviceUpdate.Change.ADD)) {
+                Tier tier = new Tier(1);
+                switchManager.setNodeProp(node, tier);
+                topology.updateHostLink(p, h, UpdateType.ADDED, null);
+            } else {
+                // No need to reset the tiering if no other hosts are currently
+                // connected
+                // If this switch was discovered to be an access switch, it
+                // still is even if the host is down
+                Tier tier = new Tier(0);
+                switchManager.setNodeProp(node, tier);
+                topology.updateHostLink(p, h, UpdateType.REMOVED, null);
+            }
+        }
+
+        if (listeners == null && newHostNotify.isEmpty()) {
             return;
         }
+        /**
+         * TODO: IfNewHostNotify is needed for current controller API. Adding
+         * logic so that existing apps (like SimpleForwardingManager) work.
+         * IDeviceListener adds additional methods and uses IListener's callback
+         * ordering. The two interfaces need to be merged.
+         */
+
+        for (IfNewHostNotify notify : newHostNotify) {
+            switch (update.change) {
+            case ADD:
+                notify.notifyHTClient(update.device.toHostNodeConnector());
+                break;
+            case DELETE:
+                notify.notifyHTClientHostRemoved(update.device
+                        .toHostNodeConnector());
+                break;
+            case CHANGE:
+            }
+        }
+
+        /**
+         * TODO: Remove this section as IDeviceListener functionality gets
+         * merged with IfNewHostNotify
+         */
         for (IDeviceListener listener : listeners) {
             switch (update.change) {
             case ADD:
@@ -1850,6 +1706,21 @@ public class DeviceManagerImpl implements IDeviceService, IEntityClassListener,
         }
     }
 
+    /**
+     * Send update notifications to listeners. IfNewHostNotify listeners need to
+     * remove old device and add new device.
+     *
+     * @param device
+     * @param oldDevice
+     */
+    protected void sendDeviceMovedNotification(Device device, Device oldDevice) {
+        for (IfNewHostNotify notify : newHostNotify) {
+            notify.notifyHTClientHostRemoved(oldDevice.toHostNodeConnector());
+            notify.notifyHTClient(device.toHostNodeConnector());
+        }
+        sendDeviceMovedNotification(device);
+    }
+
     /**
      * this method will reclassify and reconcile a device - possibilities are -
      * create new device(s), remove entities from this device. If the device
@@ -1895,25 +1766,6 @@ public class DeviceManagerImpl implements IDeviceService, IEntityClassListener,
         return true;
     }
 
-    /**
-     * For testing: sets the interval between writes of the same device to the
-     * device store.
-     *
-     * @param intervalMs
-     */
-    // void setSyncStoreWriteInterval(int intervalMs) {
-    // this.syncStoreWriteIntervalMs = intervalMs;
-    // }
-
-    /**
-     * For testing: sets the time between transition to MASTER and consolidate
-     * store
-     *
-     * @param intervalMs
-     */
-    // void setInitialSyncStoreConsolidateMs(int intervalMs) {
-    // this.initialSyncStoreConsolidateMs = intervalMs;
-    // }
 
     private long toLong(byte[] address) {
         long mac = 0;
@@ -1924,7 +1776,7 @@ public class DeviceManagerImpl implements IDeviceService, IEntityClassListener,
         return mac;
     }
 
-    /**
+     /**
      * Accepts an IPv4 address in a byte array and returns the corresponding
      * 32-bit integer value.
      *
@@ -2043,250 +1895,220 @@ public class DeviceManagerImpl implements IDeviceService, IEntityClassListener,
          */
     }
 
-    /**
-     * For testing: consolidate the store NOW
-     */
-    // void scheduleConsolidateStoreNow() {
-    // this.storeConsolidateTask.reschedule(0, TimeUnit.MILLISECONDS);
-    // }
-
-    // private class DeviceSyncManager {
-    // // maps (opaque) deviceKey to the time in System.nanoTime() when we
-    // // last wrote the device to the sync store
-    // private ConcurrentMap<Long, Long> lastWriteTimes =
-    // new ConcurrentHashMap<Long, Long>();
-    //
-    // /**
-    // * Write the given device to storage if we are MASTER.
-    // * Use this method if the device has significantly changed (e.g.,
-    // * new AP, new IP, entities removed).
-    // * @param d the device to store
-    // */
-    // public void storeDevice(Device d) {
-    // if (!isMaster)
-    // return;
-    // if (d == null)
-    // return;
-    // long now = System.nanoTime();
-    // writeUpdatedDeviceToStorage(d);
-    // lastWriteTimes.put(d.getDeviceKey(), now);
-    // }
-    //
-    // /**
-    // * Write the given device to storage if we are MASTER and if the
-    // * last write for the device was more than this.syncStoreIntervalNs
-    // * time ago.
-    // * Use this method to updated last active times in the store.
-    // * @param d the device to store
-    // */
-    // public void storeDeviceThrottled(Device d) {
-    // long intervalNs = syncStoreWriteIntervalMs*1000L*1000L;
-    // if (!isMaster)
-    // return;
-    // if (d == null)
-    // return;
-    // long now = System.nanoTime();
-    // Long last = lastWriteTimes.get(d.getDeviceKey());
-    // if (last == null ||
-    // now - last > intervalNs) {
-    // writeUpdatedDeviceToStorage(d);
-    // lastWriteTimes.put(d.getDeviceKey(), now);
-    // } else {
-    // debugCounters.updateCounter(CNT_DEVICE_STORE_THROTTLED);
-    // }
-    // }
-    //
-    // /**
-    // * Remove the given device from the store. If only some entities have
-    // * been removed the updated device should be written using
-    // * {@link #storeDevice(Device)}
-    // * @param d
-    // */
-    // public void removeDevice(Device d) {
-    // if (!isMaster)
-    // return;
-    // // FIXME: could we have a problem with concurrent put to the
-    // // hashMap? I.e., we write a stale entry to the map after the
-    // // delete and now are left with an entry we'll never clean up
-    // lastWriteTimes.remove(d.getDeviceKey());
-    // try {
-    // // TODO: should probably do versioned delete. OTOH, even
-    // // if we accidentally delete, we'll write it again after
-    // // the next entity ....
-    // debugCounters.updateCounter(CNT_DEVICE_REMOVED_FROM_STORE);
-    // storeClient.delete(DeviceSyncRepresentation.computeKey(d));
-    // } catch(ObsoleteVersionException e) {
-    // // FIXME
-    // } catch (SyncException e) {
-    // debugCounters.updateCounter(CNT_SYNC_EXCEPTION);
-    // logger.error("Could not remove device " + d + " from store", e);
-    // }
-    // }
-    //
-    // /**
-    // * Remove the given Versioned device from the store. If the device
-    // * was locally modified ignore the delete request.
-    // * @param syncedDeviceKey
-    // */
-    // private void removeDevice(Versioned<DeviceSyncRepresentation> dev) {
-    // try {
-    // debugCounters.updateCounter(CNT_DEVICE_REMOVED_FROM_STORE);
-    // storeClient.delete(dev.getValue().getKey(),
-    // dev.getVersion());
-    // } catch(ObsoleteVersionException e) {
-    // // Key was locally modified by another thread.
-    // // Do not delete and ignore.
-    // } catch(SyncException e) {
-    // debugCounters.updateCounter(CNT_SYNC_EXCEPTION);
-    // logger.error("Failed to remove device entry for " +
-    // dev.toString() + " from store.", e);
-    // }
-    // }
-    //
-    // /**
-    // * Synchronously transition from SLAVE to MASTER. By iterating through
-    // * the store and learning all devices from the store
-    // */
-    // private void goToMaster() {
-    // if (logger.isDebugEnabled()) {
-    // logger.debug("Transitioning to MASTER role");
-    // }
-    // debugCounters.updateCounter(CNT_TRANSITION_TO_MASTER);
-    // IClosableIterator<Map.Entry<String,Versioned<DeviceSyncRepresentation>>>
-    // iter = null;
-    // try {
-    // iter = storeClient.entries();
-    // } catch (SyncException e) {
-    // debugCounters.updateCounter(CNT_SYNC_EXCEPTION);
-    // logger.error("Failed to read devices from sync store", e);
-    // return;
-    // }
-    // try {
-    // while(iter.hasNext()) {
-    // Versioned<DeviceSyncRepresentation> versionedDevice =
-    // iter.next().getValue();
-    // DeviceSyncRepresentation storedDevice =
-    // versionedDevice.getValue();
-    // if (storedDevice == null)
-    // continue;
-    // debugCounters.updateCounter(CNT_DEVICES_FROM_STORE);
-    // for(SyncEntity se: storedDevice.getEntities()) {
-    // learnDeviceByEntity(se.asEntity());
-    // }
-    // }
-    // } finally {
-    // if (iter != null)
-    // iter.close();
-    // }
-    // storeConsolidateTask.reschedule(initialSyncStoreConsolidateMs,
-    // TimeUnit.MILLISECONDS);
-    // }
-    //
-    // /**
-    // * Actually perform the write of the device to the store
-    // * FIXME: concurrent modification behavior
-    // * @param device The device to write
-    // */
-    // private void writeUpdatedDeviceToStorage(Device device) {
-    // try {
-    // debugCounters.updateCounter(CNT_DEVICE_STORED);
-    // // FIXME: use a versioned put
-    // DeviceSyncRepresentation storeDevice =
-    // new DeviceSyncRepresentation(device);
-    // storeClient.put(storeDevice.getKey(), storeDevice);
-    // } catch (ObsoleteVersionException e) {
-    // // FIXME: what's the right behavior here. Can the store client
-    // // even throw this error?
-    // } catch (SyncException e) {
-    // debugCounters.updateCounter(CNT_SYNC_EXCEPTION);
-    // logger.error("Could not write device " + device +
-    // " to sync store:", e);
-    // }
-    // }
-    //
-    // /**
-    // * Iterate through all entries in the sync store. For each device
-    // * in the store check if any stored entity matches a live device. If
-    // * no entities match a live device we remove the entry from the store.
-    // *
-    // * Note: we do not check if all devices known to device manager are
-    // * in the store. We rely on regular packetIns for that.
-    // * Note: it's possible that multiple entries in the store map to the
-    // * same device. We don't check or handle this case.
-    // *
-    // * We need to perform this check after a SLAVE->MASTER transition to
-    // * get rid of all entries the old master might have written to the
-    // * store after we took over. We also run it regularly in MASTER
-    // * state to ensure we don't have stale entries in the store
-    // */
-    // private void consolidateStore() {
-    // if (!isMaster)
-    // return;
-    // debugCounters.updateCounter(CNT_CONSOLIDATE_STORE_RUNS);
-    // if (logger.isDebugEnabled()) {
-    // logger.debug("Running consolidateStore.");
-    // }
-    // IClosableIterator<Map.Entry<String,Versioned<DeviceSyncRepresentation>>>
-    // iter = null;
-    // try {
-    // iter = storeClient.entries();
-    // } catch (SyncException e) {
-    // debugCounters.updateCounter(CNT_SYNC_EXCEPTION);
-    // logger.error("Failed to read devices from sync store", e);
-    // return;
-    // }
-    // try {
-    // while(iter.hasNext()) {
-    // boolean found = false;
-    // Versioned<DeviceSyncRepresentation> versionedDevice =
-    // iter.next().getValue();
-    // DeviceSyncRepresentation storedDevice =
-    // versionedDevice.getValue();
-    // if (storedDevice == null)
-    // continue;
-    // for(SyncEntity se: storedDevice.getEntities()) {
-    // try {
-    // // Do we have a device for this entity??
-    // IDevice d = findDevice(se.macAddress, se.vlan,
-    // se.ipv4Address,
-    // se.switchDPID,
-    // se.switchPort);
-    // if (d != null) {
-    // found = true;
-    // break;
-    // }
-    // } catch (IllegalArgumentException e) {
-    // // not all key fields provided. Skip entity
-    // }
-    // }
-    // if (!found) {
-    // // We currently DO NOT have a live device that
-    // // matches the current device from the store.
-    // // Delete device from store.
-    // if (logger.isDebugEnabled()) {
-    // logger.debug("Removing device {} from store. No "
-    // + "corresponding live device",
-    // storedDevice.getKey());
-    // }
-    // debugCounters.updateCounter(CNT_CONSOLIDATE_STORE_DEVICES_REMOVED);
-    // removeDevice(versionedDevice);
-    // }
-    // }
-    // } finally {
-    // if (iter != null)
-    // iter.close();
-    // }
-    // }
-    // }
-    //
-    //
-    // /**
-    // * For testing. Sets the syncService. Only call after init but before
-    // * startUp. Used by MockDeviceManager
-    // * @param syncService
-    // */
-    // protected void setSyncServiceIfNotSet(ISyncService syncService) {
-    // if (this.syncService == null)
-    // this.syncService = syncService;
-    // }
+    @Override
+    public HostNodeConnector hostFind(InetAddress networkAddress) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public HostNodeConnector hostQuery(InetAddress networkAddress) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Future<HostNodeConnector> discoverHost(InetAddress networkAddress) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public List<List<String>> getHostNetworkHierarchy(InetAddress hostAddress) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Set<HostNodeConnector> getAllHosts() {
+        Collection<Device> devices = Collections
+                .unmodifiableCollection(deviceMap.values());
+        Iterator<Device> i = devices.iterator();
+        Set<HostNodeConnector> nc = new HashSet<HostNodeConnector>();
+        while (i.hasNext()) {
+            Device device = i.next();
+            nc.add(device.toHostNodeConnector());
+        }
+        return nc;
+    }
+
+    @Override
+    public Set<HostNodeConnector> getActiveStaticHosts() {
+        Collection<Device> devices = Collections
+                .unmodifiableCollection(deviceMap.values());
+        Iterator<Device> i = devices.iterator();
+        Set<HostNodeConnector> nc = new HashSet<HostNodeConnector>();
+        while (i.hasNext()) {
+            Device device = i.next();
+            if (device.isStaticHost())
+                nc.add(device.toHostNodeConnector());
+        }
+        return nc;
+    }
+
+    @Override
+    public Set<HostNodeConnector> getInactiveStaticHosts() {
+        Collection<Entity> devices = Collections
+                .unmodifiableCollection(inactiveStaticDevices.values());
+        Iterator<Entity> i = devices.iterator();
+        Set<HostNodeConnector> nc = new HashSet<HostNodeConnector>();
+        while (i.hasNext()) {
+            Entity ent = i.next();
+                nc.add(ent.toHostNodeConnector());
+
+        }
+        return nc;
+    }
+
+    @Override
+    public Status addStaticHost(String networkAddress, String dataLayerAddress,
+            NodeConnector nc, String vlan) {
+        Long mac = HexEncode.stringToLong(dataLayerAddress);
+        try {
+            InetAddress addr = InetAddress.getByName(networkAddress);
+            int ip = toIPv4Address(addr.getAddress());
+            Entity e = new Entity(mac, Short.valueOf(vlan), ip, nc, new Date());
+
+            if (switchManager.isNodeConnectorEnabled(e.getPort())) {
+                Device d = this.learnDeviceByEntity(e);
+                d.setStaticHost(true);
+            } else {
+                logger.debug(
+                        "Switch or switchport is not up, adding host {} to inactive list",
+                        addr.getHostName());
+                 inactiveStaticDevices.put(e.getPort(), e);
+            }
+            return new Status(StatusCode.SUCCESS);
+        } catch (UnknownHostException e) {
+            return new Status(StatusCode.INTERNALERROR);
+        }
+    }
+
+    @Override
+    public Status removeStaticHost(String networkAddress) {
+        Integer addr;
+        try {
+            addr = toIPv4Address(InetAddress.getByName(networkAddress)
+                    .getAddress());
+        } catch (UnknownHostException e) {
+            return new Status(StatusCode.NOTFOUND, "Host does not exist");
+        }
+        Iterator<Device> di = this.getDeviceIteratorForQuery(null, null, addr,
+                null);
+        List<IDeviceListener> listeners = deviceListeners.getOrderedListeners();
+        while (di.hasNext()) {
+            Device d = di.next();
+            if (d.isStaticHost()) {
+                deleteDevice(d);
+                for (IfNewHostNotify notify : newHostNotify) {
+                    notify.notifyHTClientHostRemoved(d.toHostNodeConnector());
+                }
+                for (IDeviceListener listener : listeners) {
+                    listener.deviceRemoved(d);
+                }
+            }
+        }
+        //go through inactive entites.
+        Set<HostNodeConnector> inactive = this.getInactiveStaticHosts();
+        for(HostNodeConnector nc : inactive){
+            Integer ip =toIPv4Address(nc.getNetworkAddress().getAddress());
+            if(ip.equals(addr)){
+                this.inactiveStaticDevices.remove(nc.getnodeConnector());
+            }
+        }
+
+
+        return new Status(StatusCode.SUCCESS);
+    }
+
+    @Override
+    public void notifyNode(Node node, UpdateType type,
+            Map<String, Property> propMap) {
+        if (node == null)
+            return;
+        List<IDeviceListener> listeners = deviceListeners.getOrderedListeners();
+        switch (type) {
+        case REMOVED:
+            logger.debug("Received removed node {}", node);
+            for (Entry<Long, Device> d : deviceMap.entrySet()) {
+                Device device = d.getValue();
+                HostNodeConnector host = device.toHostNodeConnector();
+                if (host.getnodeconnectorNode().equals(node)) {
+                    logger.debug("Node: {} is down, remove from Hosts_DB", node);
+                    deleteDevice(device);
+                    for (IfNewHostNotify notify : newHostNotify) {
+                        notify.notifyHTClientHostRemoved(host);
+                    }
+                    for (IDeviceListener listener : listeners) {
+                        listener.deviceRemoved(device);
+                    }
+                }
+            }
+            break;
+        default:
+            break;
+        }
+    }
+
+    @Override
+    public void notifyNodeConnector(NodeConnector nodeConnector,
+            UpdateType type, Map<String, Property> propMap) {
+        if (nodeConnector == null)
+            return;
+        List<IDeviceListener> listeners = deviceListeners.getOrderedListeners();
+        boolean up = false;
+        switch (type) {
+        case ADDED:
+            up = true;
+            break;
+        case REMOVED:
+            break;
+        case CHANGED:
+            State state = (State) propMap.get(State.StatePropName);
+            if ((state != null) && (state.getValue() == State.EDGE_UP)) {
+                up = true;
+            }
+            break;
+        default:
+            return;
+        }
+
+        if (up) {
+            logger.debug("handleNodeConnectorStatusUp {}", nodeConnector);
+
+            Entity ent = inactiveStaticDevices.get(nodeConnector);
+            Device device = this.learnDeviceByEntity(ent);
+            if(device!=null){
+                HostNodeConnector host = device.toHostNodeConnector();
+                if (host != null) {
+                    inactiveStaticDevices.remove(nodeConnector);
+                    for (IfNewHostNotify notify : newHostNotify) {
+                        notify.notifyHTClient(host);
+                    }
+                    for (IDeviceListener listener : listeners) {
+                        listener.deviceAdded(device);
+                    }
+                } else {
+                    logger.debug("handleNodeConnectorStatusDown {}", nodeConnector);
+                }
+            }
+        }else{
+                // remove all devices on the node that went down.
+                for (Entry<Long, Device> entry : deviceMap.entrySet()) {
+                    Device device = entry.getValue();
+                    HostNodeConnector host = device.toHostNodeConnector();
+                    if (host.getnodeConnector().equals(nodeConnector)) {
+                        deleteDevice(device);
+                        for (IfNewHostNotify notify : newHostNotify) {
+                            notify.notifyHTClientHostRemoved(host);
+                        }
+                        for (IDeviceListener listener : listeners) {
+                            listener.deviceRemoved(device);
+                        }
+                    }
+                }
+
+            }
+        }
+
 }