Simplified the port handling logic for VM live migration case

Change-Id: Ib28978bb2ee62c4719261c38eebb72a006f81f19
diff --git a/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/api/Constants.java b/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/api/Constants.java
index 3b6ce42..532aa90 100644
--- a/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/api/Constants.java
+++ b/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/api/Constants.java
@@ -38,17 +38,14 @@
     public static final MacAddress DEFAULT_GATEWAY_MAC = MacAddress.valueOf(DEFAULT_GATEWAY_MAC_STR);
     public static final MacAddress DEFAULT_EXTERNAL_ROUTER_MAC = MacAddress.valueOf("fe:00:00:00:00:01");
 
-    private static final String CAVIUM_PCI_VENDOR_INFO = "177d:9712";
-    private static final String PORT_NAME_PREFIX_CAVIUM = "enp";
     public static final String PCI_VENDOR_INFO = "pci_vendor_info";
     public static final String DIRECT = "direct";
     public static final String PCISLOT = "pci_slot";
 
-    private static final Map<String, String> PORT_NAME_PREFIX_MAP = createPortNamePrefixMap();
-    private static Map<String, String> createPortNamePrefixMap() {
-        //Additional pci vendor information will be added
-        return ImmutableMap.of(CAVIUM_PCI_VENDOR_INFO, PORT_NAME_PREFIX_CAVIUM);
-    }
+    public static final String ANNOTATION_NETWORK_ID = "networkId";
+    public static final String ANNOTATION_PORT_ID = "portId";
+    public static final String ANNOTATION_CREATE_TIME = "createTime";
+    public static final String ANNOTATION_SEGMENT_ID = "segId";
 
     public static final int PRIORITY_TUNNEL_TAG_RULE = 30000;
     public static final int PRIORITY_FLOATING_INTERNAL = 42000;
@@ -106,4 +103,13 @@
     public static Map<String, String> portNamePrefixMap() {
         return PORT_NAME_PREFIX_MAP;
     }
+
+    private static final String CAVIUM_PCI_VENDOR_INFO = "177d:9712";
+    private static final String PORT_NAME_PREFIX_CAVIUM = "enp";
+
+    private static final Map<String, String> PORT_NAME_PREFIX_MAP = createPortNamePrefixMap();
+    private static Map<String, String> createPortNamePrefixMap() {
+        //Additional pci vendor information will be added
+        return ImmutableMap.of(CAVIUM_PCI_VENDOR_INFO, PORT_NAME_PREFIX_CAVIUM);
+    }
 }
\ No newline at end of file
diff --git a/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/api/InstancePort.java b/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/api/InstancePort.java
index 53a8797..5247174 100644
--- a/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/api/InstancePort.java
+++ b/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/api/InstancePort.java
@@ -49,7 +49,17 @@
         /**
          * Signifies that the given instance port is in migrating state.
          */
-        MIGRATING
+        MIGRATING,
+
+        /**
+         * Signifies that the given instance port will be removed soon.
+         */
+        REMOVED,
+
+        /**
+         * Signifies that the given instance port has been migrated.
+         */
+        MIGRATED,
     }
 
     /**
@@ -88,6 +98,14 @@
     DeviceId deviceId();
 
     /**
+     * Returns the old device ID of the instance port.
+     * This method returns valid value only if the VM is in migration phase.
+     *
+     * @return device id
+     */
+    DeviceId oldDeviceId();
+
+    /**
      * Returns the port number of the instance port.
      *
      * @return port number
@@ -95,6 +113,14 @@
     PortNumber portNumber();
 
     /**
+     * Returns the old port number of the instance port.
+     * This method returns valid value only if the VM is in migration phase.
+     *
+     * @return port number
+     */
+    PortNumber oldPortNumber();
+
+    /**
      * Returns the state of the instance port.
      *
      * @return state of port
@@ -110,6 +136,15 @@
     InstancePort updateState(State newState);
 
     /**
+     * Returns new instance port instance with given prev data.
+     *
+     * @param oldDeviceId       old device ID
+     * @param oldPortNumber     old port number
+     * @return updated instance port
+     */
+    InstancePort updatePrevData(DeviceId oldDeviceId, PortNumber oldPortNumber);
+
+    /**
      * Builder of new instance port.
      */
     interface Builder {
@@ -162,6 +197,14 @@
         Builder deviceId(DeviceId deviceId);
 
         /**
+         * Returns instance port builder with supplied old Device identifier.
+         *
+         * @param oldDeviceId device identifier
+         * @return instance port builder
+         */
+        Builder oldDeviceId(DeviceId oldDeviceId);
+
+        /**
          * Returns instance port builder with supplied port number.
          *
          * @param portNumber port number
@@ -170,6 +213,14 @@
         Builder portNumber(PortNumber portNumber);
 
         /**
+         * Returns instance port builder with supplied old port number.
+         *
+         * @param oldPortNumber port number
+         * @return instance port builder
+         */
+        Builder oldPortNumber(PortNumber oldPortNumber);
+
+        /**
          * Returns instance port builder with supplied state.
          *
          * @param state state
diff --git a/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/api/InstancePortService.java b/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/api/InstancePortService.java
index d462e1b..f5ebe11 100644
--- a/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/api/InstancePortService.java
+++ b/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/api/InstancePortService.java
@@ -66,18 +66,4 @@
      * @return set of instance ports; empty list if no port exists
      */
     Set<InstancePort> instancePorts(String osNetId);
-
-    /**
-     * Processes instance port addition event caused by VM migration.
-     *
-     * @param port instance port
-     */
-    void migrationPortAdded(InstancePort port);
-
-    /**
-     * Processes instance port removal event caused by VM migration.
-     *
-     * @param port instance port
-     */
-    void migrationPortRemoved(InstancePort port);
 }
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/DefaultInstancePort.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/DefaultInstancePort.java
index b1addf0..0a53885 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/DefaultInstancePort.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/DefaultInstancePort.java
@@ -45,24 +45,30 @@
     private final MacAddress macAddress;
     private final IpAddress ipAddress;
     private final DeviceId deviceId;
+    private final DeviceId oldDeviceId;
     private final PortNumber portNumber;
+    private final PortNumber oldPortNumber;
     private final State state;
 
     // private constructor not intended for invoked from external
     private DefaultInstancePort(String networkId, String portId,
                                 MacAddress macAddress, IpAddress ipAddress,
-                                DeviceId deviceId, PortNumber portNumber,
+                                DeviceId deviceId, DeviceId oldDeviceId,
+                                PortNumber portNumber, PortNumber oldPortNumber,
                                 State state) {
         this.networkId = networkId;
         this.portId = portId;
         this.macAddress = macAddress;
         this.ipAddress = ipAddress;
         this.deviceId = deviceId;
+        this.oldDeviceId = oldDeviceId;
         this.portNumber = portNumber;
+        this.oldPortNumber = oldPortNumber;
         this.state = state;
     }
 
-    private DefaultInstancePort(Host host, State state) {
+    private DefaultInstancePort(Host host, State state,
+                                DeviceId oldDeviceId, PortNumber oldPortNumber) {
         this.networkId = host.annotations().value(ANNOTATION_NETWORK_ID);
         this.portId = host.annotations().value(ANNOTATION_PORT_ID);
         this.macAddress = host.mac();
@@ -72,6 +78,8 @@
         this.deviceId = host.location().deviceId();
         this.portNumber = host.location().port();
         this.state = state;
+        this.oldDeviceId = oldDeviceId;
+        this.oldPortNumber = oldPortNumber;
     }
 
     public static DefaultInstancePort from(Host host, State state) {
@@ -83,7 +91,22 @@
         checkArgument(!Strings.isNullOrEmpty(
                                 host.annotations().value(ANNOTATION_CREATE_TIME)));
 
-        return new DefaultInstancePort(host, state);
+        return new DefaultInstancePort(host, state, null, null);
+    }
+
+    public static DefaultInstancePort from(Host host,
+                                           State state,
+                                           DeviceId oldDeviceId,
+                                           PortNumber oldPortNumber) {
+        checkNotNull(host);
+        checkArgument(!Strings.isNullOrEmpty(
+                host.annotations().value(ANNOTATION_NETWORK_ID)));
+        checkArgument(!Strings.isNullOrEmpty(
+                host.annotations().value(ANNOTATION_PORT_ID)));
+        checkArgument(!Strings.isNullOrEmpty(
+                host.annotations().value(ANNOTATION_CREATE_TIME)));
+
+        return new DefaultInstancePort(host, state, oldDeviceId, oldPortNumber);
     }
 
     @Override
@@ -112,15 +135,34 @@
     }
 
     @Override
+    public DeviceId oldDeviceId() {
+        return oldDeviceId;
+    }
+
+    @Override
     public PortNumber portNumber() {
         return portNumber;
     }
 
     @Override
+    public PortNumber oldPortNumber() {
+        return oldPortNumber;
+    }
+
+    @Override
     public State state() {
         return state;
     }
 
+    /**
+     * Obtains an instance port builder.
+     *
+     * @return instance port builder
+     */
+    public static Builder builder() {
+        return new Builder();
+    }
+
     @Override
     public InstancePort updateState(State newState) {
         return new Builder()
@@ -129,12 +171,30 @@
                 .macAddress(macAddress)
                 .ipAddress(ipAddress)
                 .deviceId(deviceId)
+                .oldDeviceId(oldDeviceId)
                 .portNumber(portNumber)
+                .oldPortNumber(oldPortNumber)
                 .state(newState)
                 .build();
     }
 
     @Override
+    public InstancePort updatePrevData(DeviceId oldDeviceId,
+                                       PortNumber oldPortNumber) {
+        return new Builder()
+                .networkId(networkId)
+                .portId(portId)
+                .macAddress(macAddress)
+                .ipAddress(ipAddress)
+                .deviceId(deviceId)
+                .oldDeviceId(oldDeviceId)
+                .portNumber(portNumber)
+                .oldPortNumber(oldPortNumber)
+                .state(state)
+                .build();
+    }
+
+    @Override
     public String toString() {
         return MoreObjects.toStringHelper(getClass())
                 .add("networkId", networkId)
@@ -142,7 +202,9 @@
                 .add("macAddress", macAddress)
                 .add("ipAddress", ipAddress)
                 .add("deviceId", deviceId)
+                .add("oldDeviceId", oldDeviceId)
                 .add("portNumber", portNumber)
+                .add("oldPortNumber", oldPortNumber)
                 .add("state", state)
                 .toString();
     }
@@ -159,7 +221,9 @@
                     Objects.equals(macAddress, that.macAddress) &&
                     Objects.equals(ipAddress, that.ipAddress) &&
                     Objects.equals(deviceId, that.deviceId) &&
+                    Objects.equals(oldDeviceId, that.oldDeviceId) &&
                     Objects.equals(portNumber, that.portNumber) &&
+                    Objects.equals(oldPortNumber, that.oldPortNumber) &&
                     Objects.equals(state, that.state);
         }
         return false;
@@ -172,7 +236,9 @@
                 macAddress,
                 ipAddress,
                 deviceId,
+                oldDeviceId,
                 portNumber,
+                oldPortNumber,
                 state);
     }
 
@@ -186,7 +252,9 @@
         private MacAddress macAddress;
         private IpAddress ipAddress;
         private DeviceId deviceId;
+        private DeviceId oldDeviceId;
         private PortNumber portNumber;
+        private PortNumber oldPortNumber;
         private State state;
 
         // private constructor not intended to use from external
@@ -209,7 +277,9 @@
                     macAddress,
                     ipAddress,
                     deviceId,
+                    oldDeviceId,
                     portNumber,
+                    oldPortNumber,
                     state);
         }
 
@@ -244,12 +314,24 @@
         }
 
         @Override
+        public InstancePort.Builder oldDeviceId(DeviceId oldDeviceId) {
+            this.oldDeviceId = oldDeviceId;
+            return this;
+        }
+
+        @Override
         public InstancePort.Builder portNumber(PortNumber portNumber) {
             this.portNumber = portNumber;
             return this;
         }
 
         @Override
+        public InstancePort.Builder oldPortNumber(PortNumber oldPortNumber) {
+            this.oldPortNumber = oldPortNumber;
+            return this;
+        }
+
+        @Override
         public InstancePort.Builder state(State state) {
             this.state = state;
             return this;
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/DistributedInstancePortStore.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/DistributedInstancePortStore.java
index f663980..b313cce 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/DistributedInstancePortStore.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/DistributedInstancePortStore.java
@@ -48,6 +48,7 @@
 import static org.onosproject.openstacknetworking.api.Constants.OPENSTACK_NETWORKING_APP_ID;
 import static org.onosproject.openstacknetworking.api.InstancePort.State.ACTIVE;
 import static org.onosproject.openstacknetworking.api.InstancePort.State.INACTIVE;
+import static org.onosproject.openstacknetworking.api.InstancePort.State.MIGRATED;
 import static org.onosproject.openstacknetworking.api.InstancePort.State.MIGRATING;
 import static org.onosproject.openstacknetworking.api.InstancePortEvent.Type.OPENSTACK_INSTANCE_MIGRATION_ENDED;
 import static org.onosproject.openstacknetworking.api.InstancePortEvent.Type.OPENSTACK_INSTANCE_MIGRATION_STARTED;
@@ -169,12 +170,7 @@
                     break;
                 case UPDATE:
                     log.debug("Instance port updated");
-                    eventExecutor.execute(() -> {
-                            notifyDelegate(new InstancePortEvent(
-                                    OPENSTACK_INSTANCE_PORT_UPDATED,
-                                    event.newValue().value()));
-                            processInstancePortUpdate(event);
-                    });
+                    eventExecutor.execute(() -> processInstancePortUpdate(event));
                     break;
                 case REMOVE:
                     log.debug("Instance port removed");
@@ -198,25 +194,41 @@
                 notifyDelegate(new InstancePortEvent(
                         OPENSTACK_INSTANCE_MIGRATION_STARTED,
                         event.newValue().value()));
+                return;
             }
 
-            if (oldState == MIGRATING && newState == ACTIVE) {
+            if (oldState == MIGRATING && newState == MIGRATED) {
                 notifyDelegate(new InstancePortEvent(
                         OPENSTACK_INSTANCE_MIGRATION_ENDED,
                         event.newValue().value()));
+                updateInstancePort(event.newValue().value().updateState(ACTIVE));
+                return;
             }
 
             if (oldState == ACTIVE && newState == INACTIVE) {
                 notifyDelegate(new InstancePortEvent(
                         OPENSTACK_INSTANCE_TERMINATED,
                         event.newValue().value()));
+                return;
             }
 
             if (oldState == INACTIVE && newState == ACTIVE) {
                 notifyDelegate(new InstancePortEvent(
                         OPENSTACK_INSTANCE_RESTARTED,
                         event.newValue().value()));
+                return;
             }
+
+            // this should be auto-transition
+            if (oldState == MIGRATED && newState == ACTIVE) {
+                return;
+            }
+
+            notifyDelegate(new InstancePortEvent(
+                    OPENSTACK_INSTANCE_PORT_UPDATED,
+                    event.newValue().value()));
+
+            // TODO: need to handle cold migration
         }
     }
 }
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/HostBasedInstancePort.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/HostBasedInstancePort.java
deleted file mode 100644
index 12e51fe..0000000
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/HostBasedInstancePort.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright 2017-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.openstacknetworking.impl;
-
-import com.google.common.base.Strings;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.MacAddress;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Host;
-import org.onosproject.net.PortNumber;
-import org.onosproject.openstacknetworking.api.InstancePort;
-
-import java.util.Objects;
-import java.util.Optional;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static org.onosproject.openstacknetworking.api.InstancePort.State.ACTIVE;
-
-/**
- * Implementation of instance port based on host subsystem.
- * Basically, HostBasedInstancePort is just a wrapper of a host, which helps
- * mapping between OpenStack port and the OVS port and retrieving information
- * such as IP address, location, and so on.
- */
-public final class HostBasedInstancePort implements InstancePort {
-
-    static final String ANNOTATION_NETWORK_ID = "networkId";
-    static final String ANNOTATION_PORT_ID = "portId";
-    static final String ANNOTATION_CREATE_TIME = "createTime";
-
-    private final Host host;
-
-    /**
-     * Default constructor.
-     *
-     * @param instance host object of this instance
-     */
-    private HostBasedInstancePort(Host instance) {
-        this.host = instance;
-    }
-
-    /**
-     * Returns new instance.
-     *
-     * @param host host object of this instance
-     * @return instance
-     */
-    public static HostBasedInstancePort of(Host host) {
-        checkNotNull(host);
-        checkArgument(!Strings.isNullOrEmpty(host.annotations().value(ANNOTATION_NETWORK_ID)));
-        checkArgument(!Strings.isNullOrEmpty(host.annotations().value(ANNOTATION_PORT_ID)));
-        checkArgument(!Strings.isNullOrEmpty(host.annotations().value(ANNOTATION_CREATE_TIME)));
-
-        return new HostBasedInstancePort(host);
-    }
-
-    @Override
-    public String networkId() {
-        return host.annotations().value(ANNOTATION_NETWORK_ID);
-    }
-
-    @Override
-    public String portId() {
-        return host.annotations().value(ANNOTATION_PORT_ID);
-    }
-
-    @Override
-    public MacAddress macAddress() {
-        return host.mac();
-    }
-
-    @Override
-    public IpAddress ipAddress() {
-        Optional<IpAddress> ipAddr = host.ipAddresses().stream().findFirst();
-        return ipAddr.orElse(null);
-    }
-
-    @Override
-    public DeviceId deviceId() {
-        return host.location().deviceId();
-    }
-
-    @Override
-    public PortNumber portNumber() {
-        return host.location().port();
-    }
-
-    @Override
-    public State state() {
-        return ACTIVE;
-    }
-
-    @Override
-    public InstancePort updateState(State newState) {
-        return null;
-    }
-
-    @Override
-    public String toString() {
-        return host.toString();
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
-        }
-
-        if (obj instanceof HostBasedInstancePort) {
-            HostBasedInstancePort that = (HostBasedInstancePort) obj;
-            if (Objects.equals(this.portId(), that.portId())) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(portId());
-    }
-}
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/HostBasedInstancePortManager.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/HostBasedInstancePortManager.java
deleted file mode 100644
index 3378b82..0000000
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/HostBasedInstancePortManager.java
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * Copyright 2017-present Open Networking Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.openstacknetworking.impl;
-
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Maps;
-import org.apache.felix.scr.annotations.Activate;
-import org.apache.felix.scr.annotations.Component;
-import org.apache.felix.scr.annotations.Deactivate;
-import org.apache.felix.scr.annotations.Reference;
-import org.apache.felix.scr.annotations.ReferenceCardinality;
-import org.apache.felix.scr.annotations.Service;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.MacAddress;
-import org.onlab.util.Tools;
-import org.onosproject.event.ListenerRegistry;
-import org.onosproject.net.Host;
-import org.onosproject.net.HostId;
-import org.onosproject.net.host.HostEvent;
-import org.onosproject.net.host.HostListener;
-import org.onosproject.net.host.HostService;
-import org.onosproject.openstacknetworking.api.InstancePort;
-import org.onosproject.openstacknetworking.api.InstancePortEvent;
-import org.onosproject.openstacknetworking.api.InstancePortEvent.Type;
-import org.onosproject.openstacknetworking.api.InstancePortListener;
-import org.onosproject.openstacknetworking.api.InstancePortService;
-import org.slf4j.Logger;
-
-import java.util.Map;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-import static org.onosproject.openstacknetworking.api.InstancePortEvent.Type.OPENSTACK_INSTANCE_MIGRATION_ENDED;
-import static org.onosproject.openstacknetworking.api.InstancePortEvent.Type.OPENSTACK_INSTANCE_MIGRATION_STARTED;
-import static org.onosproject.openstacknetworking.api.InstancePortEvent.Type.OPENSTACK_INSTANCE_PORT_DETECTED;
-import static org.onosproject.openstacknetworking.api.InstancePortEvent.Type.OPENSTACK_INSTANCE_PORT_UPDATED;
-import static org.onosproject.openstacknetworking.api.InstancePortEvent.Type.OPENSTACK_INSTANCE_PORT_VANISHED;
-import static org.onosproject.openstacknetworking.impl.HostBasedInstancePort.ANNOTATION_NETWORK_ID;
-import static org.onosproject.openstacknetworking.impl.HostBasedInstancePort.ANNOTATION_PORT_ID;
-import static org.slf4j.LoggerFactory.getLogger;
-
-/**
- * Provides implementation of administering and interfacing host based instance ports.
- * It also provides instance port events for the hosts mapped to OpenStack VM interface.
- */
-@Service
-@Component(immediate = true)
-public class HostBasedInstancePortManager
-        extends ListenerRegistry<InstancePortEvent, InstancePortListener>
-        implements InstancePortService {
-
-    protected final Logger log = getLogger(getClass());
-
-    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected HostService hostService;
-
-    private final InternalHostListener hostListener = new InternalHostListener();
-
-    @Activate
-    protected void activate() {
-        hostService.addListener(hostListener);
-        log.info("Started");
-    }
-
-    @Deactivate
-    protected void deactivate() {
-        hostService.removeListener(hostListener);
-        log.info("Stopped");
-    }
-
-    @Override
-    public InstancePort instancePort(MacAddress macAddress) {
-        Host host = hostService.getHost(HostId.hostId(macAddress));
-        if (host == null || !isValidHost(host)) {
-            return null;
-        }
-        return HostBasedInstancePort.of(host);
-    }
-
-    @Override
-    public InstancePort instancePort(IpAddress ipAddress, String osNetId) {
-        return Tools.stream(hostService.getHosts()).filter(this::isValidHost)
-                .map(HostBasedInstancePort::of)
-                .filter(instPort -> instPort.networkId().equals(osNetId))
-                .filter(instPort -> instPort.ipAddress().equals(ipAddress))
-                .findAny().orElse(null);
-    }
-
-    @Override
-    public InstancePort instancePort(String osPortId) {
-        return Tools.stream(hostService.getHosts()).filter(this::isValidHost)
-                .map(HostBasedInstancePort::of)
-                .filter(instPort -> instPort.portId().equals(osPortId))
-                .findAny().orElse(null);
-    }
-
-    @Override
-    public Set<InstancePort> instancePorts() {
-        Set<InstancePort> instPors = Tools.stream(hostService.getHosts())
-                .filter(this::isValidHost)
-                .map(HostBasedInstancePort::of)
-                .collect(Collectors.toSet());
-        return ImmutableSet.copyOf(instPors);
-    }
-
-    @Override
-    public Set<InstancePort> instancePorts(String osNetId) {
-        Set<InstancePort> instPors = Tools.stream(hostService.getHosts())
-                .filter(this::isValidHost)
-                .map(HostBasedInstancePort::of)
-                .filter(instPort -> instPort.networkId().equals(osNetId))
-                .collect(Collectors.toSet());
-        return ImmutableSet.copyOf(instPors);
-    }
-
-    @Override
-    public void migrationPortAdded(InstancePort port) {
-        hostListener.processEvent(OPENSTACK_INSTANCE_MIGRATION_STARTED, port);
-    }
-
-    @Override
-    public void migrationPortRemoved(InstancePort port) {
-        hostListener.processEvent(OPENSTACK_INSTANCE_MIGRATION_ENDED, port);
-    }
-
-    private boolean isValidHost(Host host) {
-        return !host.ipAddresses().isEmpty() &&
-                host.annotations().value(ANNOTATION_NETWORK_ID) != null &&
-                host.annotations().value(ANNOTATION_PORT_ID) != null;
-    }
-
-    /**
-     * An internal listener that listens host event generated by HostLocationTracker
-     * in DistributedHostStore. The role of this listener is to convert host event
-     * to instance port event and post to the subscribers that have interested on
-     * this type of event.
-     */
-    private class InternalHostListener implements HostListener {
-
-        @Override
-        public boolean isRelevant(HostEvent event) {
-            Host host = event.subject();
-            if (!isValidHost(host)) {
-                log.debug("Invalid host detected, ignore it {}", host);
-                return false;
-            }
-            return true;
-        }
-
-        @Override
-        public void event(HostEvent event) {
-            InstancePort instPort = HostBasedInstancePort.of(event.subject());
-            switch (event.type()) {
-                case HOST_UPDATED:
-                    processEvent(OPENSTACK_INSTANCE_PORT_UPDATED, instPort);
-                    break;
-                case HOST_ADDED:
-                    processEvent(OPENSTACK_INSTANCE_PORT_DETECTED, instPort);
-                    break;
-                case HOST_REMOVED:
-                    processEvent(OPENSTACK_INSTANCE_PORT_VANISHED, instPort);
-                    break;
-                default:
-                    break;
-            }
-        }
-
-        private void processEvent(Type type, InstancePort port) {
-            Map<Type, String> eventMap = Maps.newConcurrentMap();
-            eventMap.put(OPENSTACK_INSTANCE_PORT_UPDATED, "updated");
-            eventMap.put(OPENSTACK_INSTANCE_PORT_DETECTED, "detected");
-            eventMap.put(OPENSTACK_INSTANCE_PORT_VANISHED, "disabled");
-            eventMap.put(OPENSTACK_INSTANCE_MIGRATION_STARTED, "detected");
-            eventMap.put(OPENSTACK_INSTANCE_MIGRATION_ENDED, "disabled");
-
-            InstancePortEvent instPortEvent = new InstancePortEvent(type, port);
-            log.debug("Instance port is {}: {}", eventMap.get(type), port);
-            process(instPortEvent);
-        }
-    }
-}
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/InstancePortManager.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/InstancePortManager.java
index c7ae7cc..7ad2b02 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/InstancePortManager.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/InstancePortManager.java
@@ -17,6 +17,7 @@
 
 import com.google.common.base.Strings;
 import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
 import org.apache.felix.scr.annotations.Activate;
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.Deactivate;
@@ -28,6 +29,7 @@
 import org.onosproject.core.CoreService;
 import org.onosproject.event.ListenerRegistry;
 import org.onosproject.net.Host;
+import org.onosproject.net.HostLocation;
 import org.onosproject.net.host.HostEvent;
 import org.onosproject.net.host.HostListener;
 import org.onosproject.net.host.HostService;
@@ -46,9 +48,12 @@
 
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onosproject.openstacknetworking.api.Constants.ANNOTATION_NETWORK_ID;
+import static org.onosproject.openstacknetworking.api.Constants.ANNOTATION_PORT_ID;
 import static org.onosproject.openstacknetworking.api.InstancePort.State.ACTIVE;
-import static org.onosproject.openstacknetworking.impl.HostBasedInstancePort.ANNOTATION_NETWORK_ID;
-import static org.onosproject.openstacknetworking.impl.HostBasedInstancePort.ANNOTATION_PORT_ID;
+import static org.onosproject.openstacknetworking.api.InstancePort.State.INACTIVE;
+import static org.onosproject.openstacknetworking.api.InstancePort.State.MIGRATED;
+import static org.onosproject.openstacknetworking.api.InstancePort.State.MIGRATING;
 import static org.slf4j.LoggerFactory.getLogger;
 
 /**
@@ -56,7 +61,7 @@
  * It also provides instance port events for the hosts mapped to OpenStack VM interface.
  */
 @Service
-@Component(immediate = false)
+@Component(immediate = true)
 public class InstancePortManager
         extends ListenerRegistry<InstancePortEvent, InstancePortListener>
         implements InstancePortService, InstancePortAdminService {
@@ -193,16 +198,6 @@
         return ImmutableSet.copyOf(ports);
     }
 
-    @Override
-    public void migrationPortAdded(InstancePort port) {
-        // TODO need to be removed
-    }
-
-    @Override
-    public void migrationPortRemoved(InstancePort port) {
-        // TODO need to be removed
-    }
-
     private boolean isInstancePortInUse(String portId) {
         // TODO add checking logic
         return false;
@@ -246,13 +241,45 @@
                     updateInstancePort(instPort);
                     break;
                 case HOST_ADDED:
-                    createInstancePort(instPort);
+                    InstancePort existingPort = instancePort(instPort.portId());
+                    if (existingPort == null) {
+                        // first time to add instance
+                        createInstancePort(instPort);
+                    } else {
+                        // the instance was restarted
+                        if (existingPort.state() == InstancePort.State.INACTIVE) {
+                            updateInstancePort(existingPort.updateState(ACTIVE));
+                        }
+                    }
                     break;
                 case HOST_REMOVED:
-                    removeInstancePort(instPort.portId());
+                    // we will remove instance port from persistent store,
+                    // only if we receive port removal signal from neutron
+                    // by default, we update the instance port state to INACTIVE
+                    // to indicate the instance is terminated
+                    updateInstancePort(instPort.updateState(INACTIVE));
                     break;
                 case HOST_MOVED:
-                    // TODO: require implementation for VM migration case
+                    Host oldHost = event.prevSubject();
+                    Host currHost = event.subject();
+
+                    // in the middle of VM migration
+                    if (oldHost.locations().size() < currHost.locations().size()) {
+                        updateInstancePort(instPort.updateState(MIGRATING));
+                    }
+
+                    // finish of VM migration
+                    if (oldHost.locations().size() > currHost.locations().size()) {
+                        Set<HostLocation> diff =
+                                Sets.difference(oldHost.locations(), currHost.locations());
+                        HostLocation location = diff.stream().findFirst().orElse(null);
+
+                        if (location != null) {
+                            InstancePort updated = instPort.updateState(MIGRATED);
+                            updateInstancePort(updated.updatePrevData(
+                                        location.deviceId(), location.port()));
+                        }
+                    }
                     break;
                 default:
                     break;
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingArpHandler.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingArpHandler.java
index 0a916d8..1f73566 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingArpHandler.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingArpHandler.java
@@ -58,8 +58,6 @@
 import org.onosproject.openstacknetworking.api.InstancePortService;
 import org.onosproject.openstacknetworking.api.OpenstackFlowRuleService;
 import org.onosproject.openstacknetworking.api.OpenstackNetworkAdminService;
-import org.onosproject.openstacknetworking.api.OpenstackNetworkEvent;
-import org.onosproject.openstacknetworking.api.OpenstackNetworkListener;
 import org.onosproject.openstacknetworking.api.OpenstackNetworkService;
 import org.onosproject.openstacknetworking.api.OpenstackRouterEvent;
 import org.onosproject.openstacknetworking.api.OpenstackRouterListener;
@@ -98,6 +96,7 @@
 import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getGwByInstancePort;
 import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getPropertyValue;
 import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.isAssociatedWithVM;
+import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.swapStaleLocation;
 import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.GATEWAY;
 import static org.slf4j.LoggerFactory.getLogger;
 
@@ -156,14 +155,12 @@
     private final OpenstackNodeListener osNodeListener = new InternalNodeEventListener();
     private final InstancePortListener instPortListener = new InternalInstancePortListener();
 
-    private final OpenstackNetworkListener osNetworkListener = new InternalOpenstackNetworkListener();
-
     private ApplicationId appId;
     private NodeId localNodeId;
+
     private final Map<String, MacAddress> floatingIpMacMap = Maps.newConcurrentMap();
-    private final Map<String, DeviceId> migrationPool = Maps.newConcurrentMap();
-    private final Map<MacAddress, InstancePort> terminatedInstPorts = Maps.newConcurrentMap();
-    private final Map<MacAddress, InstancePort> tobeRemovedInstPorts = Maps.newConcurrentMap();
+
+    // TODO: pendingInstPortIds should be purged later
     private final Map<String, NetFloatingIP> pendingInstPortIds = Maps.newConcurrentMap();
 
     private final ExecutorService eventExecutor = newSingleThreadExecutor(
@@ -178,7 +175,6 @@
         localNodeId = clusterService.getLocalNode().id();
         osRouterService.addListener(osRouterListener);
         osNodeService.addListener(osNodeListener);
-        osNetworkService.addListener(osNetworkListener);
         instancePortService.addListener(instPortListener);
         leadershipService.runForLeadership(appId.name());
         packetService.addProcessor(packetProcessor, PacketProcessor.director(1));
@@ -192,7 +188,6 @@
         osRouterService.removeListener(osRouterListener);
         osNodeService.removeListener(osNodeListener);
         instancePortService.removeListener(instPortListener);
-        osNetworkService.removeListener(osNetworkListener);
         leadershipService.withdraw(appId.name());
         eventExecutor.shutdown();
         configService.unregisterProperties(getClass(), false);
@@ -358,8 +353,7 @@
             if (f.getPortId() != null) {
                 Port port = osNetworkAdminService.port(f.getPortId());
                 if (port != null) {
-                    if (!Strings.isNullOrEmpty(port.getDeviceId()) &&
-                            instancePortService.instancePort(f.getPortId()) == null) {
+                    if (!Strings.isNullOrEmpty(port.getDeviceId())) {
                         pendingInstPortIds.put(f.getPortId(), f);
                     }
                 }
@@ -488,16 +482,6 @@
 
             instPort = instancePortService.instancePort(targetMac);
 
-            // in VM purge case, we will have null instance port
-            if (instPort == null) {
-                instPort = tobeRemovedInstPorts.get(targetMac);
-                tobeRemovedInstPorts.remove(targetMac);
-            }
-
-            if (instPort == null) {
-                instPort = terminatedInstPorts.get(targetMac);
-            }
-
             OpenstackNode gw = getGwByInstancePort(gateways, instPort);
 
             if (gw == null) {
@@ -586,38 +570,12 @@
                     );
                     break;
                 case OPENSTACK_FLOATING_IP_ASSOCIATED:
-
-                    if (instancePortService.instancePort(event.portId()) == null) {
-                        log.info("Try to associate the fip {} with a terminated VM",
-                                event.floatingIp().getFloatingIpAddress());
-                        pendingInstPortIds.put(event.portId(), event.floatingIp());
-                        return;
-                    }
-
                     eventExecutor.execute(() ->
                         // associate a floating IP with an existing VM
                         setFloatingIpArpRule(event.floatingIp(), completedGws, true)
                     );
                     break;
                 case OPENSTACK_FLOATING_IP_DISASSOCIATED:
-
-                    MacAddress mac = floatingIpMacMap.get(event.floatingIp().getFloatingIpAddress());
-
-                    if (mac != null && !tobeRemovedInstPorts.containsKey(mac) &&
-                            terminatedInstPorts.containsKey(mac)) {
-                        tobeRemovedInstPorts.put(mac, terminatedInstPorts.get(mac));
-                    }
-
-                    if (instancePortService.instancePort(event.portId()) == null) {
-
-                        if (pendingInstPortIds.containsKey(event.portId())) {
-                            log.info("Try to disassociate the fip {} with a terminated VM",
-                                    event.floatingIp().getFloatingIpAddress());
-                            pendingInstPortIds.remove(event.portId());
-                            return;
-                        }
-                    }
-
                     eventExecutor.execute(() ->
                         // disassociate a floating IP with the existing VM
                         setFloatingIpArpRule(event.floatingIp(), completedGws, false)
@@ -731,7 +689,6 @@
 
             switch (event.type()) {
                 case OPENSTACK_INSTANCE_PORT_DETECTED:
-                    terminatedInstPorts.remove(instPort.macAddress());
 
                     if (pendingInstPortIds.containsKey(instPort.portId())) {
                         Set<OpenstackNode> completedGws =
@@ -742,11 +699,6 @@
                     }
 
                     break;
-
-                case OPENSTACK_INSTANCE_PORT_VANISHED:
-                    terminatedInstPorts.put(instPort.macAddress(), instPort);
-                    break;
-
                 case OPENSTACK_INSTANCE_MIGRATION_STARTED:
 
                     if (gateways.size() == 1) {
@@ -754,25 +706,24 @@
                     }
 
                     if (fip != null && isAssociatedWithVM(osNetworkService, fip)) {
-                        migrationPool.put(fip.getFloatingIpAddress(), event.subject().deviceId());
-
-                        eventExecutor.execute(() -> {
+                        eventExecutor.execute(() ->
                             setFloatingIpArpRuleWithPortEvent(fip, event.subject(),
-                                    gateways, true);
-                        });
+                                    gateways, true)
+                        );
                     }
 
                     break;
                 case OPENSTACK_INSTANCE_MIGRATION_ENDED:
 
+                    InstancePort revisedInstPort = swapStaleLocation(event.subject());
+
                     if (gateways.size() == 1) {
                         return;
                     }
 
                     if (fip != null && isAssociatedWithVM(osNetworkService, fip)) {
-                        DeviceId newDeviceId = migrationPool.get(fip.getFloatingIpAddress());
-                        DeviceId oldDeviceId = event.subject().deviceId();
-                        migrationPool.remove(fip.getFloatingIpAddress());
+                        DeviceId newDeviceId = event.subject().deviceId();
+                        DeviceId oldDeviceId = revisedInstPort.deviceId();
 
                         OpenstackNode oldGw = getGwByComputeDevId(gateways, oldDeviceId);
                         OpenstackNode newGw = getGwByComputeDevId(gateways, newDeviceId);
@@ -782,34 +733,8 @@
                         }
 
                         eventExecutor.execute(() ->
-                                setFloatingIpArpRuleWithPortEvent(fip, event.subject(),
-                                        gateways, false));
-                    }
-                    break;
-                default:
-                    break;
-            }
-        }
-    }
-
-    private class InternalOpenstackNetworkListener implements OpenstackNetworkListener {
-
-        @Override
-        public boolean isRelevant(OpenstackNetworkEvent event) {
-            // do not allow to proceed without leadership
-            NodeId leader = leadershipService.getLeader(appId.name());
-            return Objects.equals(localNodeId, leader);
-        }
-
-        @Override
-        public void event(OpenstackNetworkEvent event) {
-            switch (event.type()) {
-                case OPENSTACK_PORT_REMOVED:
-                    Port osPort = event.port();
-                    MacAddress mac = MacAddress.valueOf(osPort.getMacAddress());
-                    if (terminatedInstPorts.containsKey(mac)) {
-                        tobeRemovedInstPorts.put(mac, terminatedInstPorts.get(mac));
-                        terminatedInstPorts.remove(mac);
+                                setFloatingIpArpRuleWithPortEvent(fip,
+                                        revisedInstPort, gateways, false));
                     }
                     break;
                 default:
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingFloatingIpHandler.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingFloatingIpHandler.java
index 831f53b..5be8b87 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingFloatingIpHandler.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingFloatingIpHandler.java
@@ -43,9 +43,9 @@
 import org.onosproject.openstacknetworking.api.Constants;
 import org.onosproject.openstacknetworking.api.ExternalPeerRouter;
 import org.onosproject.openstacknetworking.api.InstancePort;
+import org.onosproject.openstacknetworking.api.InstancePortAdminService;
 import org.onosproject.openstacknetworking.api.InstancePortEvent;
 import org.onosproject.openstacknetworking.api.InstancePortListener;
-import org.onosproject.openstacknetworking.api.InstancePortService;
 import org.onosproject.openstacknetworking.api.OpenstackFlowRuleService;
 import org.onosproject.openstacknetworking.api.OpenstackNetworkEvent;
 import org.onosproject.openstacknetworking.api.OpenstackNetworkListener;
@@ -82,11 +82,14 @@
 import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_FLOATING_EXTERNAL;
 import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_FLOATING_INTERNAL;
 import static org.onosproject.openstacknetworking.api.Constants.ROUTING_TABLE;
+import static org.onosproject.openstacknetworking.api.InstancePort.State.PENDING_REMOVAL;
+import static org.onosproject.openstacknetworking.api.InstancePort.State.REMOVED;
 import static org.onosproject.openstacknetworking.api.InstancePortEvent.Type.OPENSTACK_INSTANCE_MIGRATION_ENDED;
 import static org.onosproject.openstacknetworking.api.InstancePortEvent.Type.OPENSTACK_INSTANCE_MIGRATION_STARTED;
 import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.associatedFloatingIp;
 import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getGwByComputeDevId;
 import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.isAssociatedWithVM;
+import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.swapStaleLocation;
 import static org.onosproject.openstacknetworking.util.RulePopulatorUtil.buildExtension;
 import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.GATEWAY;
 
@@ -117,7 +120,7 @@
     protected OpenstackNodeService osNodeService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected InstancePortService instancePortService;
+    protected InstancePortAdminService instancePortService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected OpenstackRouterAdminService osRouterAdminService;
@@ -136,10 +139,7 @@
     private final OpenstackNetworkListener osNetworkListener = new InternalOpenstackNetworkListener();
     private final InstancePortListener instPortListener = new InternalInstancePortListener();
 
-    private final Map<String, DeviceId> migrationPool = Maps.newConcurrentMap();
     private Map<String, Port> terminatedOsPorts = Maps.newConcurrentMap();
-    private Map<String, InstancePort> terminatedInstPorts = Maps.newConcurrentMap();
-    private Map<String, InstancePort> tobeRemovedInstPorts = Maps.newConcurrentMap();
     private Map<String, NetFloatingIP> pendingInstPortIds = Maps.newConcurrentMap();
 
     private ApplicationId appId;
@@ -189,21 +189,16 @@
         InstancePort instPort = instancePortService.instancePort(srcMac);
 
         if (instPort == null) {
-            instPort = tobeRemovedInstPorts.get(osPort.getId());
-            tobeRemovedInstPorts.remove(osPort.getId());
-        }
-
-        if (instPort == null) {
-            instPort = terminatedInstPorts.get(osPort.getId());
-        }
-
-        if (instPort == null) {
             final String errorFormat = ERR_FLOW + "no host(MAC:%s) found";
             final String error = String.format(errorFormat,
                     floatingIp.getFloatingIpAddress(), srcMac);
             throw new IllegalStateException(error);
         }
 
+        if (instPort.state() == PENDING_REMOVAL) {
+            instancePortService.updateInstancePort(instPort.updateState(REMOVED));
+        }
+
         ExternalPeerRouter externalPeerRouter = externalPeerRouter(osNet);
         if (externalPeerRouter == null) {
             final String errorFormat = ERR_FLOW + "no external peer router found";
@@ -638,12 +633,6 @@
         // set floating IP rules only if the port is associated to a VM
         if (!Strings.isNullOrEmpty(osPort.getDeviceId())) {
 
-            if (!tobeRemovedInstPorts.containsKey(osPort.getId()) &&
-                    terminatedInstPorts.containsKey(osPort.getId())) {
-                tobeRemovedInstPorts.put(osPort.getId(),
-                                    terminatedInstPorts.get(osPort.getId()));
-            }
-
             if (instancePortService.instancePort(osPort.getId()) == null) {
 
                 // in case there is pending instance port, we simply remove that
@@ -753,15 +742,6 @@
                                 continue;
                             }
 
-                            // This is for handling a VM, which is associated
-                            // with a floating IP, was terminated case
-                            // in this case, we cannot obtain instance port
-                            // information from a terminated VM, we simply
-                            // construct a pending map where key is terminated
-                            // instance port ID while value is floating IP
-                            // address which supposed to be associated with the
-                            // terminated instance port.
-
                             // Note that, at OPENSTACK_INSTANCE_PORT_DETECTED phase,
                             // we will install floating IP related rules by
                             // referring to the key and value stored in pending map
@@ -770,6 +750,7 @@
                                 pendingInstPortIds.put(fip.getPortId(), fip);
                                 continue;
                             }
+
                             setFloatingIpRules(fip, osPort, event.subject(), true);
                         }
                     });
@@ -863,7 +844,6 @@
                     if (instPort != null && instPort.portId() != null) {
                         String portId = instPort.portId();
 
-                        terminatedInstPorts.remove(portId);
                         terminatedOsPorts.remove(portId);
 
                         Port port = osNetworkService.port(portId);
@@ -877,19 +857,6 @@
 
                     break;
 
-                case OPENSTACK_INSTANCE_PORT_VANISHED:
-                    if (instPort != null && instPort.portId() != null) {
-                        String portId = instPort.portId();
-                        Port port = osNetworkService.port(portId);
-
-                        if (port != null) {
-                            terminatedInstPorts.put(portId, instPort);
-                            terminatedOsPorts.put(portId, port);
-                        }
-                    }
-
-                    break;
-
                 case OPENSTACK_INSTANCE_MIGRATION_STARTED:
 
                     fip = associatedFloatingIp(event.subject(), ips);
@@ -923,14 +890,13 @@
                         // corresponding compute node, we need to install new rule to
                         // the target compute node, and remove rules from original node
                         setComputeNodeToGatewayHelper(event.subject(), osNet, gateways, true);
-
-                        migrationPool.put(fip.getFloatingIpAddress(), event.subject().deviceId());
-
                     });
                     break;
                 case OPENSTACK_INSTANCE_MIGRATION_ENDED:
 
-                    fip = associatedFloatingIp(event.subject(), ips);
+                    InstancePort revisedInstPort = swapStaleLocation(event.subject());
+
+                    fip = associatedFloatingIp(revisedInstPort, ips);
 
                     if (fip == null) {
                         return;
@@ -956,9 +922,8 @@
                     // if it is true, we simply do not remove the rules, as
                     // it has been overwritten at port detention event
                     // if it is false, we will remove the rules
-                    DeviceId newDeviceId = migrationPool.get(fip.getFloatingIpAddress());
-                    DeviceId oldDeviceId = event.subject().deviceId();
-                    migrationPool.remove(fip.getFloatingIpAddress());
+                    DeviceId newDeviceId = event.subject().deviceId();
+                    DeviceId oldDeviceId = revisedInstPort.deviceId();
 
                     OpenstackNode oldGateway = getGwByComputeDevId(gateways, oldDeviceId);
                     OpenstackNode newGateway = getGwByComputeDevId(gateways, newDeviceId);
@@ -971,13 +936,13 @@
 
                         // We need to remove the old ComputeNodeToGateway rules from
                         // original compute node
-                        setComputeNodeToGatewayHelper(event.subject(), osNet, gateways, false);
+                        setComputeNodeToGatewayHelper(revisedInstPort, osNet, gateways, false);
 
                         // Since DownstreamExternal rules should only be placed in
                         // corresponding gateway node, we need to remove old rule from
                         // the corresponding gateway node
-                        setDownstreamExternalRulesHelper(fip, osNet,
-                                event.subject(), externalPeerRouter, gateways, false);
+                        setDownstreamExternalRulesHelper(fip, osNet, revisedInstPort,
+                                externalPeerRouter, gateways, false);
                     });
                     break;
                 default:
@@ -999,10 +964,23 @@
         public void event(OpenstackNetworkEvent event) {
             switch (event.type()) {
                 case OPENSTACK_PORT_REMOVED:
-                    Port osPort = event.port();
-                    if (terminatedInstPorts.containsKey(osPort.getId())) {
-                        updateFipStore(terminatedInstPorts.get(osPort.getId()));
-                        terminatedInstPorts.remove(osPort.getId());
+                    String portId = event.port().getId();
+                    terminatedOsPorts.put(portId, event.port());
+
+                    InstancePort instPort = instancePortService.instancePort(portId);
+                    InstancePort updated = instPort.updateState(PENDING_REMOVAL);
+                    instancePortService.updateInstancePort(updated);
+
+                    updateFipStore(instPort);
+
+                    // we will hold the instance port in its store, until its
+                    // state is changed to REMOVED
+                    while (true) {
+                        if (instancePortService.instancePort(portId).state() ==
+                                REMOVED) {
+                            instancePortService.removeInstancePort(portId);
+                            break;
+                        }
                     }
                     break;
                 default:
@@ -1029,7 +1007,6 @@
                     // invalidate bound fixed IP and port
                     neutronFip.setFixedIpAddress(null);
                     neutronFip.setPortId(null);
-                    tobeRemovedInstPorts.put(port.portId(), port);
 
                     // Following update will in turn trigger
                     // OPENSTACK_FLOATING_IP_DISASSOCIATED event
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingHandler.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingHandler.java
index 45928ba..03f65aa 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingHandler.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingHandler.java
@@ -1072,30 +1072,39 @@
         public void event(InstancePortEvent event) {
             InstancePort instPort = event.subject();
             switch (event.type()) {
-                case OPENSTACK_INSTANCE_PORT_UPDATED:
                 case OPENSTACK_INSTANCE_PORT_DETECTED:
-                    eventExecutor.execute(() -> {
-                        log.info("RoutingHandler: Instance port detected MAC:{} IP:{}",
-                                instPort.macAddress(),
-                                instPort.ipAddress());
-                        instPortDetected(event.subject());
-                    });
+                case OPENSTACK_INSTANCE_PORT_UPDATED:
+                    log.info("RoutingHandler: Instance port detected MAC:{} IP:{}",
+                                                            instPort.macAddress(),
+                                                            instPort.ipAddress());
+
+                    eventExecutor.execute(() -> instPortDetected(event.subject()));
+
                     break;
                 case OPENSTACK_INSTANCE_PORT_VANISHED:
-                    eventExecutor.execute(() -> {
-                        log.info("RoutingHandler: Instance port vanished MAC:{} IP:{}",
-                                instPort.macAddress(),
-                                instPort.ipAddress());
-                        instPortRemoved(event.subject());
-                    });
+                    log.info("RoutingHandler: Instance port vanished MAC:{} IP:{}",
+                                                            instPort.macAddress(),
+                                                            instPort.ipAddress());
+
+                    eventExecutor.execute(() -> instPortRemoved(event.subject()));
+
+                    break;
+                case OPENSTACK_INSTANCE_MIGRATION_STARTED:
+                    log.info("RoutingHandler: Migration started for MAC:{} IP:{}",
+                                                            instPort.macAddress(),
+                                                            instPort.ipAddress());
+
+                    eventExecutor.execute(() -> instPortDetected(instPort));
+
                     break;
                 case OPENSTACK_INSTANCE_MIGRATION_ENDED:
+                    log.info("RoutingHandler: Migration finished for MAC:{} IP:{}",
+                                                            instPort.macAddress(),
+                                                            instPort.ipAddress());
                     eventExecutor.execute(() -> {
-                        log.info("RoutingHandler: Instance port vanished MAC:{} IP:{} due to VM migration",
-                                instPort.macAddress(),
-                                instPort.ipAddress());
                         // TODO: need to reconfigure rules to point to update VM
                     });
+
                     break;
                 default:
                     break;
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingIcmpHandler.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingIcmpHandler.java
index 292ea3f..e5289a2 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingIcmpHandler.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingIcmpHandler.java
@@ -120,7 +120,8 @@
     private static final KryoNamespace SERIALIZER_ICMP_MAP = KryoNamespace.newBuilder()
             .register(KryoNamespaces.API)
             .register(InstancePort.class)
-            .register(HostBasedInstancePort.class)
+            .register(DefaultInstancePort.class)
+            .register(InstancePort.State.class)
             .build();
 
     private ApplicationId appId;
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSecurityGroupHandler.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSecurityGroupHandler.java
index 7fa85a9..d659c4d 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSecurityGroupHandler.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSecurityGroupHandler.java
@@ -640,8 +640,8 @@
         public void event(InstancePortEvent event) {
             InstancePort instPort = event.subject();
             switch (event.type()) {
-                case OPENSTACK_INSTANCE_PORT_UPDATED:
                 case OPENSTACK_INSTANCE_PORT_DETECTED:
+                case OPENSTACK_INSTANCE_PORT_UPDATED:
                     log.debug("Instance port detected MAC:{} IP:{}",
                             instPort.macAddress(),
                             instPort.ipAddress());
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingArpHandler.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingArpHandler.java
index fa72289..3131263 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingArpHandler.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingArpHandler.java
@@ -86,6 +86,7 @@
 import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_ARP_REQUEST_RULE;
 import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_ARP_SUBNET_RULE;
 import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getPropertyValue;
+import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.swapStaleLocation;
 import static org.onosproject.openstacknetworking.util.RulePopulatorUtil.buildExtension;
 import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.COMPUTE;
 
@@ -749,8 +750,8 @@
         @Override
         public void event(InstancePortEvent event) {
             switch (event.type()) {
-                case OPENSTACK_INSTANCE_PORT_UPDATED:
                 case OPENSTACK_INSTANCE_PORT_DETECTED:
+                case OPENSTACK_INSTANCE_PORT_UPDATED:
                     setArpRequestRule(event.subject(), true);
                     setArpReplyRule(event.subject(), true);
                     break;
@@ -758,8 +759,13 @@
                     setArpRequestRule(event.subject(), false);
                     setArpReplyRule(event.subject(), false);
                     break;
+                case OPENSTACK_INSTANCE_MIGRATION_STARTED:
+                    setArpRequestRule(event.subject(), true);
+                    setArpReplyRule(event.subject(), true);
+                    break;
                 case OPENSTACK_INSTANCE_MIGRATION_ENDED:
-                    setArpRequestRule(event.subject(), false);
+                    InstancePort revisedInstPort = swapStaleLocation(event.subject());
+                    setArpRequestRule(revisedInstPort, false);
                     break;
                 default:
                     break;
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingHandler.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingHandler.java
index 18116a9..75cdea1 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingHandler.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingHandler.java
@@ -69,6 +69,7 @@
 import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_TUNNEL_TAG_RULE;
 import static org.onosproject.openstacknetworking.api.Constants.STAT_FLAT_OUTBOUND_TABLE;
 import static org.onosproject.openstacknetworking.api.Constants.VTAG_TABLE;
+import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.swapStaleLocation;
 import static org.onosproject.openstacknetworking.util.RulePopulatorUtil.buildExtension;
 import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.COMPUTE;
 import static org.slf4j.LoggerFactory.getLogger;
@@ -608,39 +609,39 @@
             InstancePort instPort = event.subject();
 
             switch (event.type()) {
-                case OPENSTACK_INSTANCE_PORT_UPDATED:
                 case OPENSTACK_INSTANCE_PORT_DETECTED:
-                    log.info("Instance port detected MAC:{} IP:{}",
+                case OPENSTACK_INSTANCE_PORT_UPDATED:
+                    log.info("SwitchingHandler: Instance port detected MAC:{} IP:{}",
                                                         instPort.macAddress(),
                                                         instPort.ipAddress());
-                    eventExecutor.execute(() ->
-                        instPortDetected(instPort)
-                    );
+
+                    eventExecutor.execute(() -> instPortDetected(instPort));
 
                     break;
                 case OPENSTACK_INSTANCE_PORT_VANISHED:
-                    log.info("Instance port vanished MAC:{} IP:{}",
+                    log.info("SwitchingHandler: Instance port vanished MAC:{} IP:{}",
                                                         instPort.macAddress(),
                                                         instPort.ipAddress());
-                    eventExecutor.execute(() ->
-                        instPortRemoved(instPort)
-                    );
+
+                    eventExecutor.execute(() -> instPortRemoved(instPort));
 
                     break;
-
-                // we do not consider MIGRATION_STARTED case, because the rules
-                // will be installed to corresponding switches at
-                // OPENSTACK_INSTANCE_PORT_UPDATED phase
-
-                // TODO: we may need to consider to refactor the VM migration
-                // event detection logic for better code readability
-                case OPENSTACK_INSTANCE_MIGRATION_ENDED:
-                    log.info("Instance port vanished MAC:{} IP:{}, " +
-                                 "due to VM migration", instPort.macAddress(),
+                case OPENSTACK_INSTANCE_MIGRATION_STARTED:
+                    log.info("SwitchingHandler: Migration started for MAC:{} IP:{}",
+                                                        instPort.macAddress(),
                                                         instPort.ipAddress());
-                    eventExecutor.execute(() ->
-                        removeVportRules(instPort)
-                    );
+
+                    eventExecutor.execute(() -> instPortDetected(instPort));
+
+                    break;
+                case OPENSTACK_INSTANCE_MIGRATION_ENDED:
+                    log.info("SwitchingHandler: Migration finished for MAC:{} IP:{}",
+                                                        instPort.macAddress(),
+                                                        instPort.ipAddress());
+
+                    InstancePort revisedInstPort = swapStaleLocation(instPort);
+                    eventExecutor.execute(() -> removeVportRules(revisedInstPort));
+
                     break;
                 default:
                     break;
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingHostProvider.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingHostProvider.java
index 6094e72..b2af7b3 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingHostProvider.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingHostProvider.java
@@ -16,8 +16,6 @@
 package org.onosproject.openstacknetworking.impl;
 
 import com.google.common.base.Strings;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
 import org.apache.felix.scr.annotations.Activate;
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.Deactivate;
@@ -32,9 +30,7 @@
 import org.onosproject.mastership.MastershipService;
 import org.onosproject.net.ConnectPoint;
 import org.onosproject.net.DefaultAnnotations;
-import org.onosproject.net.DefaultHost;
 import org.onosproject.net.Device;
-import org.onosproject.net.DeviceId;
 import org.onosproject.net.Host;
 import org.onosproject.net.HostId;
 import org.onosproject.net.HostLocation;
@@ -50,8 +46,7 @@
 import org.onosproject.net.host.HostService;
 import org.onosproject.net.provider.AbstractProvider;
 import org.onosproject.net.provider.ProviderId;
-import org.onosproject.openstacknetworking.api.InstancePort;
-import org.onosproject.openstacknetworking.api.InstancePortService;
+import org.onosproject.openstacknetworking.api.InstancePortAdminService;
 import org.onosproject.openstacknetworking.api.OpenstackNetworkService;
 import org.onosproject.openstacknode.api.OpenstackNode;
 import org.onosproject.openstacknode.api.OpenstackNodeEvent;
@@ -62,7 +57,7 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.Map;
+import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
@@ -70,11 +65,12 @@
 
 import static org.onlab.util.Tools.groupedThreads;
 import static org.onosproject.net.AnnotationKeys.PORT_NAME;
+import static org.onosproject.openstacknetworking.api.Constants.ANNOTATION_CREATE_TIME;
+import static org.onosproject.openstacknetworking.api.Constants.ANNOTATION_NETWORK_ID;
+import static org.onosproject.openstacknetworking.api.Constants.ANNOTATION_PORT_ID;
+import static org.onosproject.openstacknetworking.api.Constants.ANNOTATION_SEGMENT_ID;
 import static org.onosproject.openstacknetworking.api.Constants.OPENSTACK_NETWORKING_APP_ID;
 import static org.onosproject.openstacknetworking.api.Constants.portNamePrefixMap;
-import static org.onosproject.openstacknetworking.impl.HostBasedInstancePort.ANNOTATION_CREATE_TIME;
-import static org.onosproject.openstacknetworking.impl.HostBasedInstancePort.ANNOTATION_NETWORK_ID;
-import static org.onosproject.openstacknetworking.impl.HostBasedInstancePort.ANNOTATION_PORT_ID;
 import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.CONTROLLER;
 
 @Service
@@ -85,7 +81,6 @@
 
     private static final String PORT_NAME_PREFIX_VM = "tap";
     private static final String ERR_ADD_HOST = "Failed to add host: ";
-    private static final String ANNOTATION_SEGMENT_ID = "segId";
     private static final String SONA_HOST_SCHEME = "sona";
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
@@ -110,7 +105,7 @@
     protected OpenstackNodeService osNodeService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected InstancePortService instancePortService;
+    protected InstancePortAdminService instancePortAdminService;
 
     private final ExecutorService deviceEventExecutor =
             Executors.newSingleThreadExecutor(groupedThreads("openstacknetworking", "device-event"));
@@ -119,9 +114,6 @@
 
     private HostProviderService hostProvider;
 
-    private Map<HostId, Device> hostDeviceMap = Maps.newConcurrentMap();
-    private Set<Host> migratingHosts = Sets.newConcurrentHashSet();
-
     /**
      * Creates OpenStack switching host provider.
      */
@@ -183,58 +175,55 @@
             return;
         }
 
-        MacAddress macAddr = MacAddress.valueOf(osPort.getMacAddress());
+        MacAddress mac = MacAddress.valueOf(osPort.getMacAddress());
+        HostId hostId = HostId.hostId(mac);
+
+        // typically one openstack port should only be bound to one fix IP address;
+        // however, openstack4j binds multiple fixed IPs to one port, this might
+        // be a defect of openstack4j implementation
+
+        // TODO: we need to find a way to bind multiple ports from multiple
+        // openstack networks into one host sooner or later
         Set<IpAddress> fixedIps = osPort.getFixedIps().stream()
-                .map(ip -> IpAddress.valueOf(ip.getIpAddress()))
-                .collect(Collectors.toSet());
+                                    .map(ip -> IpAddress.valueOf(ip.getIpAddress()))
+                                    .collect(Collectors.toSet());
+
+        // connect point is the combination of switch ID with port number where
+        // the host is attached to
         ConnectPoint connectPoint = new ConnectPoint(port.element().id(), port.number());
-        HostId oldHostId = HostId.hostId(macAddr);
 
-        // In VM migration case, a duplicated host port (port created in at new
-        // compute node) will be detected at OVS; in this case, we will store
-        // the old host instance into migration list, and overwrite old host
-        // with new host instance issue host creation event to ONOS core
-        Device oldDevice = hostDeviceMap.get(oldHostId);
+        long createTime = System.currentTimeMillis();
 
-        if (device != null && oldDevice != null && !oldDevice.equals(device)) {
-            Host host = hostService.getHost(oldHostId);
-            if (host != null) {
-                migratingHosts.add(host);
+        // we check whether the host already attached to some locations
+        Host host = hostService.getHost(hostId);
+        if (host != null) {
+            Set<HostLocation> locations = host.locations().stream()
+                    .filter(l -> l.deviceId().equals(connectPoint.deviceId()))
+                    .filter(l -> l.port().equals(connectPoint.port()))
+                    .collect(Collectors.toSet());
+            if (locations.size() == 0) {
+                hostProvider.addLocationToHost(hostId,
+                                    new HostLocation(connectPoint, createTime));
             }
-        }
+        } else {
 
-        if (device != null) {
-            hostDeviceMap.put(oldHostId, device);
-        }
+            DefaultAnnotations.Builder annotations = DefaultAnnotations.builder()
+                    .set(ANNOTATION_NETWORK_ID, osPort.getNetworkId())
+                    .set(ANNOTATION_PORT_ID, osPort.getId())
+                    .set(ANNOTATION_CREATE_TIME, String.valueOf(createTime));
 
-        DefaultAnnotations.Builder annotations = DefaultAnnotations.builder()
-                .set(ANNOTATION_NETWORK_ID, osPort.getNetworkId())
-                .set(ANNOTATION_PORT_ID, osPort.getId())
-                .set(ANNOTATION_CREATE_TIME, String.valueOf(System.currentTimeMillis()));
+            // FLAT does not require segment ID
+            if (osNet.getNetworkType() != NetworkType.FLAT) {
+                annotations.set(ANNOTATION_SEGMENT_ID, osNet.getProviderSegID());
+            }
 
-        if (osNet.getNetworkType() != NetworkType.FLAT) {
-            annotations.set(ANNOTATION_SEGMENT_ID, osNet.getProviderSegID());
-
-        }
-
-        long currentTime = System.currentTimeMillis();
-
-        HostDescription hostDesc = new DefaultHostDescription(
-                macAddr,
-                VlanId.NONE,
-                new HostLocation(connectPoint, currentTime),
-                fixedIps,
-                annotations.build());
-
-        HostId hostId = HostId.hostId(macAddr);
-        hostProvider.hostDetected(hostId, hostDesc, false);
-
-        if (device != null && oldDevice != null && !oldDevice.equals(device)) {
-            Host oldHost = hostService.getHost(oldHostId);
-            Host newHost = new DefaultHost(oldHost.providerId(), hostId, macAddr,
-                    VlanId.NONE, new HostLocation(connectPoint, currentTime),
-                    fixedIps, annotations.build());
-            instancePortService.migrationPortAdded(HostBasedInstancePort.of(newHost));
+            HostDescription hostDesc = new DefaultHostDescription(
+                    mac,
+                    VlanId.NONE,
+                    new HostLocation(connectPoint, createTime),
+                    fixedIps,
+                    annotations.build());
+            hostProvider.hostDetected(hostId, hostDesc, false);
         }
     }
 
@@ -248,33 +237,26 @@
      */
     private void processPortRemoved(DeviceEvent event) {
         Port port = event.port();
-        DeviceId deviceId = event.subject().id();
         ConnectPoint connectPoint = new ConnectPoint(port.element().id(), port.number());
 
-        Set<Host> hostsToBeRemoved = hostService.getConnectedHosts(connectPoint);
+        Set<Host> hosts = hostService.getConnectedHosts(connectPoint);
 
-        if (hostsToBeRemoved.size() == 0) {
+        hosts.forEach(h -> {
+            Optional<HostLocation> hostLocation = h.locations().stream()
+                    .filter(l -> l.deviceId().equals(port.element().id()))
+                    .filter(l -> l.port().equals(port.number())).findAny();
 
-            for (Host host : migratingHosts) {
-                if (host.location() == null) {
-                    continue;
-                }
-                String hostLocation = host.location().toString();
-                StringBuilder deviceIdWithPort = new StringBuilder();
-                deviceIdWithPort.append(deviceId.toString());
-                deviceIdWithPort.append("/");
-                deviceIdWithPort.append(port.number().toString());
-
-                if (hostLocation.equals(deviceIdWithPort.toString())) {
-                    InstancePort instPort = HostBasedInstancePort.of(host);
-                    instancePortService.migrationPortRemoved(instPort);
-                    migratingHosts.remove(host);
-                }
+            // if the host contains only one filtered location, we remove the host
+            if (h.locations().size() == 1) {
+                hostProvider.hostVanished(h.id());
             }
 
-        } else {
-            hostsToBeRemoved.forEach(host -> hostProvider.hostVanished(host.id()));
-        }
+            // if the host contains multiple locations, we simply remove the
+            // host location
+            if (h.locations().size() > 1 && hostLocation.isPresent()) {
+                hostProvider.removeLocationFromHost(h.id(), hostLocation.get());
+            }
+        });
     }
 
     /**
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/util/OpenstackNetworkingUtil.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/util/OpenstackNetworkingUtil.java
index 609b580..c384a44 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/util/OpenstackNetworkingUtil.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/util/OpenstackNetworkingUtil.java
@@ -24,6 +24,7 @@
 import org.onosproject.openstacknetworking.api.InstancePort;
 import org.onosproject.openstacknetworking.api.OpenstackNetworkService;
 import org.onosproject.openstacknetworking.api.OpenstackRouterAdminService;
+import org.onosproject.openstacknetworking.impl.DefaultInstancePort;
 import org.onosproject.openstacknode.api.OpenstackAuth;
 import org.onosproject.openstacknode.api.OpenstackAuth.Perspective;
 import org.onosproject.openstacknode.api.OpenstackNode;
@@ -383,6 +384,25 @@
     }
 
     /**
+     * Swaps current location with old location info.
+     * The revised instance port will be used to mod the flow rules after migration.
+     *
+     * @param instPort instance port
+     * @return location swapped instance port
+     */
+    public static InstancePort swapStaleLocation(InstancePort instPort) {
+        return DefaultInstancePort.builder()
+                .deviceId(instPort.oldDeviceId())
+                .portNumber(instPort.oldPortNumber())
+                .state(instPort.state())
+                .ipAddress(instPort.ipAddress())
+                .macAddress(instPort.macAddress())
+                .networkId(instPort.networkId())
+                .portId(instPort.portId())
+                .build();
+    }
+
+    /**
      * Builds up and a complete endpoint URL from gateway node.
      *
      * @param node gateway node
diff --git a/apps/openstacknetworking/app/src/test/java/org/onosproject/openstacknetworking/impl/DefaultInstancePortTest.java b/apps/openstacknetworking/app/src/test/java/org/onosproject/openstacknetworking/impl/DefaultInstancePortTest.java
index 6fecc1a..50e8f01 100644
--- a/apps/openstacknetworking/app/src/test/java/org/onosproject/openstacknetworking/impl/DefaultInstancePortTest.java
+++ b/apps/openstacknetworking/app/src/test/java/org/onosproject/openstacknetworking/impl/DefaultInstancePortTest.java
@@ -35,8 +35,8 @@
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.is;
 import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+import static org.onosproject.openstacknetworking.api.Constants.ANNOTATION_CREATE_TIME;
 import static org.onosproject.openstacknetworking.api.InstancePort.State.ACTIVE;
-import static org.onosproject.openstacknetworking.impl.HostBasedInstancePort.ANNOTATION_CREATE_TIME;
 
 /**
  * Unit tests for the default instance port class.
diff --git a/apps/openstacknetworking/app/src/test/java/org/onosproject/openstacknetworking/impl/InstancePortManagerTest.java b/apps/openstacknetworking/app/src/test/java/org/onosproject/openstacknetworking/impl/InstancePortManagerTest.java
index 9070452..8b325a3 100644
--- a/apps/openstacknetworking/app/src/test/java/org/onosproject/openstacknetworking/impl/InstancePortManagerTest.java
+++ b/apps/openstacknetworking/app/src/test/java/org/onosproject/openstacknetworking/impl/InstancePortManagerTest.java
@@ -49,8 +49,10 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
+import static org.onosproject.openstacknetworking.api.Constants.ANNOTATION_CREATE_TIME;
 import static org.onosproject.openstacknetworking.api.InstancePort.State.ACTIVE;
 import static org.onosproject.openstacknetworking.api.InstancePort.State.INACTIVE;
+import static org.onosproject.openstacknetworking.api.InstancePort.State.MIGRATED;
 import static org.onosproject.openstacknetworking.api.InstancePort.State.MIGRATING;
 import static org.onosproject.openstacknetworking.api.InstancePortEvent.Type.OPENSTACK_INSTANCE_MIGRATION_ENDED;
 import static org.onosproject.openstacknetworking.api.InstancePortEvent.Type.OPENSTACK_INSTANCE_MIGRATION_STARTED;
@@ -59,7 +61,6 @@
 import static org.onosproject.openstacknetworking.api.InstancePortEvent.Type.OPENSTACK_INSTANCE_PORT_VANISHED;
 import static org.onosproject.openstacknetworking.api.InstancePortEvent.Type.OPENSTACK_INSTANCE_RESTARTED;
 import static org.onosproject.openstacknetworking.api.InstancePortEvent.Type.OPENSTACK_INSTANCE_TERMINATED;
-import static org.onosproject.openstacknetworking.impl.HostBasedInstancePort.ANNOTATION_CREATE_TIME;
 
 /**
  * Unit tests for instance port manager.
@@ -311,8 +312,7 @@
                 1, target.instancePorts().size());
         assertNotNull("Instance port did not match", target.instancePort(PORT_ID_1));
 
-        validateEvents(OPENSTACK_INSTANCE_PORT_DETECTED,
-                OPENSTACK_INSTANCE_PORT_UPDATED, OPENSTACK_INSTANCE_TERMINATED);
+        validateEvents(OPENSTACK_INSTANCE_PORT_DETECTED, OPENSTACK_INSTANCE_TERMINATED);
     }
 
     /**
@@ -330,8 +330,7 @@
                 1, target.instancePorts().size());
         assertNotNull("Instance port did not match", target.instancePort(PORT_ID_1));
 
-        validateEvents(OPENSTACK_INSTANCE_PORT_DETECTED,
-                OPENSTACK_INSTANCE_PORT_UPDATED, OPENSTACK_INSTANCE_RESTARTED);
+        validateEvents(OPENSTACK_INSTANCE_PORT_DETECTED, OPENSTACK_INSTANCE_RESTARTED);
     }
 
     /**
@@ -342,15 +341,14 @@
         InstancePort instancePort = instancePort1;
         target.createInstancePort(instancePort);
 
-        InstancePort inactiveInstancePort = instancePort.updateState(MIGRATING);
-        target.updateInstancePort(inactiveInstancePort);
+        InstancePort migratingPort = instancePort.updateState(MIGRATING);
+        target.updateInstancePort(migratingPort);
 
         assertEquals("Number of instance port did not match",
                 1, target.instancePorts().size());
         assertNotNull("Instance port did not match", target.instancePort(PORT_ID_1));
 
-        validateEvents(OPENSTACK_INSTANCE_PORT_DETECTED,
-                OPENSTACK_INSTANCE_PORT_UPDATED, OPENSTACK_INSTANCE_MIGRATION_STARTED);
+        validateEvents(OPENSTACK_INSTANCE_PORT_DETECTED, OPENSTACK_INSTANCE_MIGRATION_STARTED);
     }
 
     /**
@@ -359,17 +357,17 @@
     @Test
     public void testMigrateInstanceEnd() {
         InstancePort instancePort = instancePort1;
-        InstancePort inactiveInstancePort = instancePort.updateState(MIGRATING);
+        InstancePort migratingPort = instancePort.updateState(MIGRATING);
+        target.createInstancePort(migratingPort);
 
-        target.createInstancePort(inactiveInstancePort);
-        target.updateInstancePort(instancePort);
+        InstancePort migratedPort = instancePort.updateState(MIGRATED);
+        target.updateInstancePort(migratedPort);
 
         assertEquals("Number of instance port did not match",
                 1, target.instancePorts().size());
         assertNotNull("Instance port did not match", target.instancePort(PORT_ID_1));
 
-        validateEvents(OPENSTACK_INSTANCE_PORT_DETECTED,
-                OPENSTACK_INSTANCE_PORT_UPDATED, OPENSTACK_INSTANCE_MIGRATION_ENDED);
+        validateEvents(OPENSTACK_INSTANCE_PORT_DETECTED, OPENSTACK_INSTANCE_MIGRATION_ENDED);
     }
 
     /**
@@ -393,8 +391,7 @@
                 0, target.instancePorts().size());
         assertNull("Instance port did not match", target.instancePort(PORT_ID_1));
 
-        validateEvents(OPENSTACK_INSTANCE_PORT_DETECTED,
-                OPENSTACK_INSTANCE_PORT_UPDATED, OPENSTACK_INSTANCE_TERMINATED,
+        validateEvents(OPENSTACK_INSTANCE_PORT_DETECTED, OPENSTACK_INSTANCE_TERMINATED,
                 OPENSTACK_INSTANCE_PORT_VANISHED);
     }
 
@@ -419,8 +416,7 @@
                 0, target.instancePorts().size());
         assertNull("Instance port did not match", target.instancePort(PORT_ID_1));
 
-        validateEvents(OPENSTACK_INSTANCE_PORT_DETECTED,
-                OPENSTACK_INSTANCE_PORT_UPDATED, OPENSTACK_INSTANCE_MIGRATION_STARTED,
+        validateEvents(OPENSTACK_INSTANCE_PORT_DETECTED, OPENSTACK_INSTANCE_MIGRATION_STARTED,
                 OPENSTACK_INSTANCE_PORT_VANISHED);
     }
 
diff --git a/apps/openstacknetworking/app/src/test/java/org/onosproject/openstacknetworking/impl/InstancePortServiceAdapter.java b/apps/openstacknetworking/app/src/test/java/org/onosproject/openstacknetworking/impl/InstancePortServiceAdapter.java
index 64c7747..885c7d8 100644
--- a/apps/openstacknetworking/app/src/test/java/org/onosproject/openstacknetworking/impl/InstancePortServiceAdapter.java
+++ b/apps/openstacknetworking/app/src/test/java/org/onosproject/openstacknetworking/impl/InstancePortServiceAdapter.java
@@ -54,14 +54,6 @@
     }
 
     @Override
-    public void migrationPortAdded(InstancePort port) {
-    }
-
-    @Override
-    public void migrationPortRemoved(InstancePort port) {
-    }
-
-    @Override
     public void addListener(InstancePortListener listener) {
 
     }
diff --git a/apps/openstacknetworking/app/src/test/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingArpHandlerTest.java b/apps/openstacknetworking/app/src/test/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingArpHandlerTest.java
index a40aacc..53cba29 100644
--- a/apps/openstacknetworking/app/src/test/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingArpHandlerTest.java
+++ b/apps/openstacknetworking/app/src/test/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingArpHandlerTest.java
@@ -223,11 +223,21 @@
         }
 
         @Override
+        public DeviceId oldDeviceId() {
+            return null;
+        }
+
+        @Override
         public PortNumber portNumber() {
             return null;
         }
 
         @Override
+        public PortNumber oldPortNumber() {
+            return null;
+        }
+
+        @Override
         public State state() {
             return null;
         }
@@ -236,6 +246,11 @@
         public InstancePort updateState(State newState) {
             return null;
         }
+
+        @Override
+        public InstancePort updatePrevData(DeviceId oldDeviceId, PortNumber oldPortNumber) {
+            return null;
+        }
     }
 
     /**
diff --git a/apps/openstacknetworking/app/src/test/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingDhcpHandlerTest.java b/apps/openstacknetworking/app/src/test/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingDhcpHandlerTest.java
index 75bec3c..530d947 100644
--- a/apps/openstacknetworking/app/src/test/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingDhcpHandlerTest.java
+++ b/apps/openstacknetworking/app/src/test/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingDhcpHandlerTest.java
@@ -545,11 +545,21 @@
         }
 
         @Override
+        public DeviceId oldDeviceId() {
+            return null;
+        }
+
+        @Override
         public PortNumber portNumber() {
             return null;
         }
 
         @Override
+        public PortNumber oldPortNumber() {
+            return null;
+        }
+
+        @Override
         public State state() {
             return null;
         }
@@ -558,6 +568,11 @@
         public InstancePort updateState(State newState) {
             return null;
         }
+
+        @Override
+        public InstancePort updatePrevData(DeviceId oldDeviceId, PortNumber oldPortNumber) {
+            return null;
+        }
     }
 
     /**