[ONOS-6241] (vNet) Can't find a virtual device Id

fix for ONOS-6241.
If there are two virtual devices with same deviceId on
the different tenant, our virtual network service failed
to return deviceId.

Change-Id: I7d2000a085406af9b003e52367d6de0f9990d6f0
diff --git a/incubator/store/src/main/java/org/onosproject/incubator/store/virtual/impl/DistributedVirtualNetworkStore.java b/incubator/store/src/main/java/org/onosproject/incubator/store/virtual/impl/DistributedVirtualNetworkStore.java
index 529a0cd..6447916 100644
--- a/incubator/store/src/main/java/org/onosproject/incubator/store/virtual/impl/DistributedVirtualNetworkStore.java
+++ b/incubator/store/src/main/java/org/onosproject/incubator/store/virtual/impl/DistributedVirtualNetworkStore.java
@@ -73,6 +73,7 @@
 
 import java.util.HashSet;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicBoolean;
@@ -125,7 +126,7 @@
             });
 
     // Listener for virtual device events
-    private final MapEventListener<DeviceId, VirtualDevice> virtualDeviceMapListener =
+    private final MapEventListener<VirtualDeviceId, VirtualDevice> virtualDeviceMapListener =
             new InternalMapListener<>((mapEventType, virtualDevice) -> {
                 VirtualNetworkEvent.Type eventType =
                         mapEventType.equals(MapEvent.Type.INSERT)
@@ -143,8 +144,8 @@
     private Map<TenantId, Set<NetworkId>> tenantIdNetworkIdSetMap;
 
     // Track virtual devices by device Id
-    private ConsistentMap<DeviceId, VirtualDevice> deviceIdVirtualDeviceConsistentMap;
-    private Map<DeviceId, VirtualDevice> deviceIdVirtualDeviceMap;
+    private ConsistentMap<VirtualDeviceId, VirtualDevice> deviceIdVirtualDeviceConsistentMap;
+    private Map<VirtualDeviceId, VirtualDevice> deviceIdVirtualDeviceMap;
 
     // Track device IDs by network Id
     private ConsistentMap<NetworkId, Set<DeviceId>> networkIdDeviceIdSetConsistentMap;
@@ -181,6 +182,7 @@
                            .register(VirtualNetwork.class)
                            .register(DefaultVirtualNetwork.class)
                            .register(VirtualDevice.class)
+                           .register(VirtualDeviceId.class)
                            .register(DefaultVirtualDevice.class)
                            .register(VirtualHost.class)
                            .register(DefaultVirtualHost.class)
@@ -226,7 +228,7 @@
                 .build();
         tenantIdNetworkIdSetMap = tenantIdNetworkIdSetConsistentMap.asJavaMap();
 
-        deviceIdVirtualDeviceConsistentMap = storageService.<DeviceId, VirtualDevice>consistentMapBuilder()
+        deviceIdVirtualDeviceConsistentMap = storageService.<VirtualDeviceId, VirtualDevice>consistentMapBuilder()
                 .withSerializer(SERIALIZER)
                 .withName("onos-deviceId-virtualdevice")
                 .withRelaxedReadConsistency()
@@ -395,17 +397,20 @@
         return (networkIdVirtualNetworkMap.containsKey(networkId));
     }
 
-
     @Override
     public VirtualDevice addDevice(NetworkId networkId, DeviceId deviceId) {
         checkState(networkExists(networkId), "The network has not been added.");
+
         Set<DeviceId> deviceIdSet = networkIdDeviceIdSetMap.get(networkId);
         if (deviceIdSet == null) {
             deviceIdSet = new HashSet<>();
         }
+
+        checkState(!deviceIdSet.contains(deviceId), "The device already exists.");
+
         VirtualDevice virtualDevice = new DefaultVirtualDevice(networkId, deviceId);
         //TODO update both maps in one transaction.
-        deviceIdVirtualDeviceMap.put(deviceId, virtualDevice);
+        deviceIdVirtualDeviceMap.put(new VirtualDeviceId(networkId, deviceId), virtualDevice);
         deviceIdSet.add(deviceId);
         networkIdDeviceIdSetMap.put(networkId, deviceIdSet);
         return virtualDevice;
@@ -428,7 +433,7 @@
             }
         });
 
-        if (deviceIdSet != null) {
+        if (!deviceIdSet.isEmpty()) {
             networkIdDeviceIdSetMap.compute(networkId, (id, existingDeviceIds) -> {
                 if (existingDeviceIds == null || existingDeviceIds.isEmpty()) {
                     return new HashSet<>();
@@ -437,7 +442,7 @@
                 }
             });
 
-            deviceIdVirtualDeviceMap.remove(deviceId);
+            deviceIdVirtualDeviceMap.remove(new VirtualDeviceId(networkId, deviceId));
         }
     }
 
@@ -598,7 +603,7 @@
             virtualPortSet = new HashSet<>();
         }
 
-        VirtualDevice device = deviceIdVirtualDeviceMap.get(deviceId);
+        VirtualDevice device = deviceIdVirtualDeviceMap.get(new VirtualDeviceId(networkId, deviceId));
         checkNotNull(device, "The device has not been created for deviceId: " + deviceId);
 
         checkState(!virtualPortExists(networkId, deviceId, portNumber),
@@ -625,7 +630,7 @@
                         p.number().equals(portNumber)).findFirst();
         checkState(virtualPortOptional.isPresent(), "The virtual port has not been added.");
 
-        VirtualDevice device = deviceIdVirtualDeviceMap.get(deviceId);
+        VirtualDevice device = deviceIdVirtualDeviceMap.get(new VirtualDeviceId(networkId, deviceId));
         checkNotNull(device, "The device has not been created for deviceId: "
                 + deviceId);
 
@@ -641,7 +646,7 @@
     @Override
     public void removePort(NetworkId networkId, DeviceId deviceId, PortNumber portNumber) {
         checkState(networkExists(networkId), "The network has not been added.");
-        VirtualDevice device = deviceIdVirtualDeviceMap.get(deviceId);
+        VirtualDevice device = deviceIdVirtualDeviceMap.get(new VirtualDeviceId(networkId, deviceId));
         checkNotNull(device, "The device has not been created for deviceId: "
                 + deviceId);
 
@@ -721,7 +726,8 @@
         Set<DeviceId> deviceIdSet = networkIdDeviceIdSetMap.get(networkId);
         Set<VirtualDevice> virtualDeviceSet = new HashSet<>();
         if (deviceIdSet != null) {
-            deviceIdSet.forEach(deviceId -> virtualDeviceSet.add(deviceIdVirtualDeviceMap.get(deviceId)));
+            deviceIdSet.forEach(deviceId -> virtualDeviceSet.add(
+                    deviceIdVirtualDeviceMap.get(new VirtualDeviceId(networkId, deviceId))));
         }
         return ImmutableSet.copyOf(virtualDeviceSet);
     }
@@ -930,4 +936,46 @@
             }
         }
     }
+
+    /**
+     * A wrapper class to isolate device id from other virtual networks.
+     */
+
+    private static class VirtualDeviceId {
+
+        NetworkId networkId;
+        DeviceId deviceId;
+
+        public VirtualDeviceId(NetworkId networkId, DeviceId deviceId) {
+            this.networkId = networkId;
+            this.deviceId = deviceId;
+        }
+
+        public NetworkId getNetworkId() {
+            return networkId;
+        }
+
+        public DeviceId getDeviceId() {
+            return deviceId;
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(networkId, deviceId);
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            }
+
+            if (obj instanceof VirtualDeviceId) {
+                VirtualDeviceId that = (VirtualDeviceId) obj;
+                return this.deviceId.equals(that.deviceId) &&
+                        this.networkId.equals(that.networkId);
+            }
+            return false;
+        }
+    }
 }