Initial support VM live migration for kubevirt

Change-Id: I28f97c7766168d53eb4c9243dc77a17136db4833
diff --git a/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/KubevirtPortEvent.java b/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/KubevirtPortEvent.java
index 2c2012a..895518d 100644
--- a/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/KubevirtPortEvent.java
+++ b/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/KubevirtPortEvent.java
@@ -29,6 +29,8 @@
     private final String securityGroupId;
     private final DeviceId deviceId;
 
+    private final KubevirtPort oldPort;
+
     /**
      * Creates an event of a given type for the specified port.
      *
@@ -39,6 +41,7 @@
         super(type, subject);
         securityGroupId = null;
         deviceId = null;
+        oldPort = null;
     }
 
     /**
@@ -52,6 +55,7 @@
         super(type, subject);
         this.securityGroupId = securityGroupId;
         this.deviceId = null;
+        this.oldPort = null;
     }
 
     /**
@@ -64,6 +68,22 @@
     public KubevirtPortEvent(Type type, KubevirtPort subject, DeviceId deviceId) {
         super(type, subject);
         this.deviceId = deviceId;
+        this.oldPort = null;
+        this.securityGroupId = null;
+    }
+
+    /**
+     * Creates an event of a given type of the specified port.
+     *
+     * @param type              kubevirt port event type
+     * @param subject           kubevirt port subject
+     * @param oldSubject        kubevirt old port object
+     * @param deviceId          kubevirt device ID
+     */
+    public KubevirtPortEvent(Type type, KubevirtPort subject, KubevirtPort oldSubject, DeviceId deviceId) {
+        super(type, subject);
+        this.deviceId = deviceId;
+        this.oldPort = oldSubject;
         this.securityGroupId = null;
     }
 
@@ -93,6 +113,11 @@
         KUBEVIRT_PORT_DEVICE_ADDED,
 
         /**
+         * Signifies that the kubevirt port has been migrated to another device.
+         */
+        KUBEVIRT_PORT_MIGRATED,
+
+        /**
          * Signifies that the kubevirt security group rule is added to a specific port.
          */
         KUBEVIRT_PORT_SECURITY_GROUP_ADDED,
@@ -112,6 +137,15 @@
         return securityGroupId;
     }
 
+    /**
+     * Returns the old subject.
+     *
+     * @return old subject
+     */
+    public KubevirtPort oldSubject() {
+        return oldPort;
+    }
+
     @Override
     public String toString() {
         return toStringHelper(this)
diff --git a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/DistributedKubevirtPortStore.java b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/DistributedKubevirtPortStore.java
index 15461df..3367d1f 100644
--- a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/DistributedKubevirtPortStore.java
+++ b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/DistributedKubevirtPortStore.java
@@ -51,6 +51,7 @@
 import static org.onlab.util.Tools.groupedThreads;
 import static org.onosproject.kubevirtnetworking.api.KubevirtPortEvent.Type.KUBEVIRT_PORT_CREATED;
 import static org.onosproject.kubevirtnetworking.api.KubevirtPortEvent.Type.KUBEVIRT_PORT_DEVICE_ADDED;
+import static org.onosproject.kubevirtnetworking.api.KubevirtPortEvent.Type.KUBEVIRT_PORT_MIGRATED;
 import static org.onosproject.kubevirtnetworking.api.KubevirtPortEvent.Type.KUBEVIRT_PORT_REMOVED;
 import static org.onosproject.kubevirtnetworking.api.KubevirtPortEvent.Type.KUBEVIRT_PORT_SECURITY_GROUP_ADDED;
 import static org.onosproject.kubevirtnetworking.api.KubevirtPortEvent.Type.KUBEVIRT_PORT_SECURITY_GROUP_REMOVED;
@@ -219,6 +220,12 @@
                         KUBEVIRT_PORT_DEVICE_ADDED, newPort, newDeviceId
                 ));
             }
+
+            if (oldDeviceId != null && newDeviceId != null && !oldDeviceId.equals(newDeviceId)) {
+                notifyDelegate(new KubevirtPortEvent(
+                        KUBEVIRT_PORT_MIGRATED, newPort, oldPort, newDeviceId
+                ));
+            }
         }
     }
 }
diff --git a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtNetworkHandler.java b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtNetworkHandler.java
index 1ea11e5..5bc1548 100644
--- a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtNetworkHandler.java
+++ b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtNetworkHandler.java
@@ -1378,6 +1378,10 @@
                 case KUBEVIRT_PORT_REMOVED:
                     eventExecutor.execute(() -> processPortDeletion(event.subject()));
                     break;
+                case KUBEVIRT_PORT_MIGRATED:
+                    eventExecutor.execute(() -> processPortCreation(event.subject()));
+                    eventExecutor.execute(() -> processPortDeletion(event.oldSubject()));
+                    break;
                 default:
                     //do nothing
                     break;
diff --git a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtRoutingSnatHandler.java b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtRoutingSnatHandler.java
index 4e3f811..716ec9c 100644
--- a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtRoutingSnatHandler.java
+++ b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtRoutingSnatHandler.java
@@ -790,6 +790,10 @@
                 case KUBEVIRT_PORT_REMOVED:
                     eventExecutor.execute(() -> processPortDeletion(event.subject()));
                     break;
+                case KUBEVIRT_PORT_MIGRATED:
+                    eventExecutor.execute(() -> processPortCreation(event.subject()));
+                    eventExecutor.execute(() -> processPortDeletion(event.oldSubject()));
+                    break;
                 default:
                     //do nothing
                     break;
diff --git a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtSwitchingTenantHandler.java b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtSwitchingTenantHandler.java
index 3d0045d..8c76ed4 100644
--- a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtSwitchingTenantHandler.java
+++ b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtSwitchingTenantHandler.java
@@ -404,6 +404,10 @@
                 case KUBEVIRT_PORT_REMOVED:
                     eventExecutor.execute(() -> processPortRemoval(event.subject()));
                     break;
+                case KUBEVIRT_PORT_MIGRATED:
+                    eventExecutor.execute(() -> processPortUpdate(event.subject()));
+                    eventExecutor.execute(() -> processPortRemoval(event.oldSubject()));
+                    break;
                 default:
                     // do nothing
                     break;
diff --git a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtVmiWatcher.java b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtVmiWatcher.java
index 9e0ce3e..414fa9e 100644
--- a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtVmiWatcher.java
+++ b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtVmiWatcher.java
@@ -225,10 +225,12 @@
                 KubevirtPort existing = portAdminService.port(port.macAddress());
 
                 if (existing != null) {
-                    if (port.deviceId() != null && existing.deviceId() == null) {
-                        KubevirtPort updated = existing.updateDeviceId(port.deviceId());
-                        // internal we update device ID of kubevirt port
-                        portAdminService.updatePort(updated);
+                    if (port.deviceId() != null) {
+                        if (existing.deviceId() == null || existing.deviceId() != port.deviceId()) {
+                            KubevirtPort updated = existing.updateDeviceId(port.deviceId());
+                            // internally we update device ID of kubevirt port
+                            portAdminService.updatePort(updated);
+                        }
                     }
                 }
             });