ONOS-5682 Trigger DeviceEvent when virtual device or port is added/updated/removed

Change-Id: I4f9b62551c4106c5dd8d2ccc977a09e4e8c93a43
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkEvent.java b/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkEvent.java
index 7234b70..3644ab6 100644
--- a/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkEvent.java
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkEvent.java
@@ -98,18 +98,6 @@
     }
 
     /**
-     * Creates an event of a given type and for the specified subject and the
-     * virtual port.
-     *
-     * @param type          event type
-     * @param subject       event subject
-     * @param virtualPort   virtual port
-     */
-    public VirtualNetworkEvent(Type type, NetworkId subject, VirtualPort virtualPort) {
-        this(type, subject, null, virtualPort);
-    }
-
-    /**
      * Creates an event of a given type and for the specified subject, virtual device and
      * virtual port.
      *
@@ -118,7 +106,7 @@
      * @param virtualDevice virtual device
      * @param virtualPort   virtual port
      */
-    private VirtualNetworkEvent(Type type, NetworkId subject, VirtualDevice virtualDevice,
+    public VirtualNetworkEvent(Type type, NetworkId subject, VirtualDevice virtualDevice,
                                 VirtualPort virtualPort) {
         super(type, subject);
         this.virtualDevice = virtualDevice;
@@ -181,7 +169,7 @@
 
     /**
      * Returns virtual device affected by event - may be null (for events relating to
-     * tenants, virtual networks and virtual ports).
+     * tenants and virtual networks).
      *
      * @return virtual device
      */
diff --git a/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkDeviceManager.java b/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkDeviceManager.java
index 5f8f433..c529061 100644
--- a/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkDeviceManager.java
+++ b/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkDeviceManager.java
@@ -19,6 +19,8 @@
 import com.google.common.collect.ImmutableList;
 import org.onosproject.incubator.net.virtual.NetworkId;
 import org.onosproject.incubator.net.virtual.VirtualDevice;
+import org.onosproject.incubator.net.virtual.VirtualNetworkEvent;
+import org.onosproject.incubator.net.virtual.VirtualNetworkListener;
 import org.onosproject.incubator.net.virtual.VirtualNetworkService;
 import org.onosproject.incubator.net.virtual.VirtualPort;
 import org.onosproject.incubator.net.virtual.event.AbstractVirtualListenerManager;
@@ -28,6 +30,7 @@
 import org.onosproject.net.Port;
 import org.onosproject.net.PortNumber;
 import org.onosproject.net.device.DeviceEvent;
+import org.onosproject.net.device.DeviceEvent.Type;
 import org.onosproject.net.device.DeviceListener;
 import org.onosproject.net.device.DeviceService;
 import org.onosproject.net.device.PortStatistics;
@@ -48,6 +51,7 @@
     private static final String TYPE_NULL = "Type cannot be null";
     private static final String DEVICE_NULL = "Device cannot be null";
     private static final String PORT_NUMBER_NULL = "PortNumber cannot be null";
+    private VirtualNetworkListener virtualNetworkListener = new InternalVirtualNetworkListener();
 
     /**
      * Creates a new VirtualNetworkDeviceService object.
@@ -58,6 +62,7 @@
     public VirtualNetworkDeviceManager(VirtualNetworkService virtualNetworkManager,
                                        NetworkId networkId) {
         super(virtualNetworkManager, networkId);
+        manager.addListener(virtualNetworkListener);
     }
 
     @Override
@@ -176,4 +181,44 @@
         // TODO not supported at this time
         return null;
     }
+
+    /**
+     * Translates VirtualNetworkEvent to DeviceEvent.
+     */
+    private class InternalVirtualNetworkListener implements VirtualNetworkListener {
+        @Override
+        public boolean isRelevant(VirtualNetworkEvent event) {
+            return networkId().equals(event.subject());
+        }
+
+        @Override
+        public void event(VirtualNetworkEvent event) {
+            switch (event.type()) {
+                case VIRTUAL_DEVICE_ADDED:
+                    post(new DeviceEvent(Type.DEVICE_ADDED, event.virtualDevice()));
+                    break;
+                case VIRTUAL_DEVICE_UPDATED:
+                    post(new DeviceEvent(Type.DEVICE_UPDATED, event.virtualDevice()));
+                    break;
+                case VIRTUAL_DEVICE_REMOVED:
+                    post(new DeviceEvent(Type.DEVICE_REMOVED, event.virtualDevice()));
+                    break;
+                case VIRTUAL_PORT_ADDED:
+                    post(new DeviceEvent(Type.PORT_ADDED, event.virtualDevice(), event.virtualPort()));
+                    break;
+                case VIRTUAL_PORT_UPDATED:
+                    post(new DeviceEvent(Type.PORT_UPDATED, event.virtualDevice(), event.virtualPort()));
+                    break;
+                case VIRTUAL_PORT_REMOVED:
+                    post(new DeviceEvent(Type.PORT_REMOVED, event.virtualDevice(), event.virtualPort()));
+                    break;
+                case NETWORK_UPDATED:
+                case NETWORK_REMOVED:
+                case NETWORK_ADDED:
+                default:
+                    // do nothing
+                    break;
+            }
+        }
+    }
 }
diff --git a/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkManager.java b/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkManager.java
index b1316a1..11a7990 100644
--- a/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkManager.java
+++ b/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkManager.java
@@ -46,6 +46,8 @@
 import org.onosproject.incubator.net.virtual.VirtualNetworkStoreDelegate;
 import org.onosproject.incubator.net.virtual.VirtualPort;
 import org.onosproject.incubator.net.virtual.VnetService;
+import org.onosproject.incubator.net.virtual.event.VirtualEvent;
+import org.onosproject.incubator.net.virtual.event.VirtualListenerRegistryManager;
 import org.onosproject.incubator.net.virtual.provider.VirtualNetworkProvider;
 import org.onosproject.incubator.net.virtual.provider.VirtualNetworkProviderRegistry;
 import org.onosproject.incubator.net.virtual.provider.VirtualNetworkProviderService;
@@ -57,8 +59,8 @@
 import org.onosproject.net.PortNumber;
 import org.onosproject.net.device.DeviceService;
 import org.onosproject.net.flow.FlowRuleService;
-import org.onosproject.net.group.GroupService;
 import org.onosproject.net.flowobjective.FlowObjectiveService;
+import org.onosproject.net.group.GroupService;
 import org.onosproject.net.host.HostService;
 import org.onosproject.net.intent.IntentEvent;
 import org.onosproject.net.intent.IntentListener;
@@ -142,6 +144,8 @@
     public void activate() {
         store.setDelegate(delegate);
         eventDispatcher.addSink(VirtualNetworkEvent.class, listenerRegistry);
+        eventDispatcher.addSink(VirtualEvent.class,
+                                VirtualListenerRegistryManager.getInstance());
         intentService.addListener(intentListener);
         appId = coreService.registerApplication(VIRTUAL_NETWORK_APP_ID_STRING);
         log.info("Started");
@@ -151,6 +155,7 @@
     public void deactivate() {
         store.unsetDelegate(delegate);
         eventDispatcher.removeSink(VirtualNetworkEvent.class);
+        eventDispatcher.removeSink(VirtualEvent.class);
         intentService.removeListener(intentListener);
         log.info("Stopped");
     }
diff --git a/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkDeviceManagerTest.java b/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkDeviceManagerTest.java
index 44099e3..aa548d3 100644
--- a/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkDeviceManagerTest.java
+++ b/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkDeviceManagerTest.java
@@ -17,15 +17,19 @@
 package org.onosproject.incubator.net.virtual.impl;
 
 import com.google.common.collect.Iterators;
+import com.google.common.collect.Lists;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
+import org.onlab.junit.TestTools;
 import org.onlab.junit.TestUtils;
 import org.onlab.osgi.TestServiceDirectory;
 import org.onosproject.common.event.impl.TestEventDispatcher;
 import org.onosproject.core.CoreService;
 import org.onosproject.core.CoreServiceAdapter;
 import org.onosproject.core.IdGenerator;
+import org.onosproject.event.Event;
+import org.onosproject.event.EventDeliveryService;
 import org.onosproject.incubator.net.virtual.TenantId;
 import org.onosproject.incubator.net.virtual.VirtualDevice;
 import org.onosproject.incubator.net.virtual.VirtualNetwork;
@@ -33,16 +37,21 @@
 import org.onosproject.incubator.store.virtual.impl.DistributedVirtualNetworkStore;
 import org.onosproject.net.ConnectPoint;
 import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
 import org.onosproject.net.MastershipRole;
 import org.onosproject.net.NetTestTools;
 import org.onosproject.net.PortNumber;
-import org.onosproject.net.TestDeviceParams;
+import org.onosproject.net.device.DeviceEvent;
+import org.onosproject.net.device.DeviceListener;
 import org.onosproject.net.device.DeviceService;
 import org.onosproject.net.intent.FakeIntentManager;
 import org.onosproject.net.intent.TestableIntentService;
 import org.onosproject.store.service.TestStorageService;
 
+import java.util.ArrayList;
 import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
 import java.util.concurrent.atomic.AtomicLong;
 
 import static org.junit.Assert.*;
@@ -50,7 +59,7 @@
 /**
  * Junit tests for VirtualNetworkDeviceService.
  */
-public class VirtualNetworkDeviceManagerTest extends TestDeviceParams {
+public class VirtualNetworkDeviceManagerTest extends VirtualNetworkTestUtil {
     private final String tenantIdValue1 = "TENANT_ID1";
 
     private VirtualNetworkManager manager;
@@ -58,6 +67,8 @@
     private CoreService coreService;
     private TestableIntentService intentService = new FakeIntentManager();
     private TestServiceDirectory testDirectory;
+    private TestListener testListener = new TestListener();
+    private TestEventDispatcher dispatcher = new TestEventDispatcher();
 
     @Before
     public void setUp() throws Exception {
@@ -72,7 +83,7 @@
         manager.store = virtualNetworkManagerStore;
         manager.intentService = intentService;
         manager.coreService = coreService;
-        NetTestTools.injectEventDispatcher(manager, new TestEventDispatcher());
+        NetTestTools.injectEventDispatcher(manager, dispatcher);
 
         testDirectory = new TestServiceDirectory();
         TestUtils.setField(manager, "serviceDirectory", testDirectory);
@@ -335,6 +346,91 @@
     }
 
     /**
+     * Tests DeviceEvents received during virtual device/port addition and removal.
+     */
+    @Test
+    public void testDeviceEventsForAddRemovalDeviceAndPorts() throws TestUtils.TestUtilsException {
+        manager.registerTenantId(TenantId.tenantId(tenantIdValue1));
+        VirtualNetwork virtualNetwork = manager.createVirtualNetwork(TenantId.tenantId(tenantIdValue1));
+
+        // add virtual device before virtual device manager is created
+        VirtualDevice device1 = manager.createVirtualDevice(virtualNetwork.id(), VDID1);
+        validateEvents(); // no DeviceEvent expected
+
+        testDirectory.add(EventDeliveryService.class, dispatcher);
+        DeviceService deviceService = manager.get(virtualNetwork.id(), DeviceService.class);
+
+        // virtual device manager is created; register DeviceEvent listener
+        deviceService.addListener(testListener);
+
+        // list to keep track of expected event types
+        List<DeviceEvent.Type> expectedEventTypes = new ArrayList<>();
+
+        // add virtual device
+        VirtualDevice device2 = manager.createVirtualDevice(virtualNetwork.id(), VDID2);
+        expectedEventTypes.add(DeviceEvent.Type.DEVICE_ADDED);
+
+        ConnectPoint cp = new ConnectPoint(PHYDID1, PortNumber.portNumber(1));
+
+        // add 2 virtual ports
+        manager.createVirtualPort(virtualNetwork.id(),
+                                  device2.id(), PortNumber.portNumber(1), cp);
+        expectedEventTypes.add(DeviceEvent.Type.PORT_ADDED);
+        manager.createVirtualPort(virtualNetwork.id(),
+                                  device2.id(), PortNumber.portNumber(2), cp);
+        expectedEventTypes.add(DeviceEvent.Type.PORT_ADDED);
+
+        // verify virtual ports were added
+        Set<VirtualPort> virtualPorts = manager.getVirtualPorts(virtualNetwork.id(), device2.id());
+        assertNotNull("The virtual port set should not be null", virtualPorts);
+        assertEquals("The virtual port set size did not match.", 2, virtualPorts.size());
+
+        // remove 2 virtual ports
+        for (VirtualPort virtualPort : virtualPorts) {
+            manager.removeVirtualPort(virtualNetwork.id(),
+                                      (DeviceId) virtualPort.element().id(), virtualPort.number());
+            expectedEventTypes.add(DeviceEvent.Type.PORT_REMOVED);
+            // attempt to remove the same virtual port again - no DeviceEvent.Type.PORT_REMOVED expected.
+            manager.removeVirtualPort(virtualNetwork.id(),
+                                      (DeviceId) virtualPort.element().id(), virtualPort.number());
+        }
+
+        // verify virtual ports were removed
+        virtualPorts = manager.getVirtualPorts(virtualNetwork.id(), device2.id());
+        assertTrue("The virtual port set should be empty.", virtualPorts.isEmpty());
+
+        // Add/remove one virtual port again.
+        VirtualPort virtualPort =
+                manager.createVirtualPort(virtualNetwork.id(), device2.id(),
+                                                            PortNumber.portNumber(1), cp);
+        expectedEventTypes.add(DeviceEvent.Type.PORT_ADDED);
+
+        ConnectPoint newCp = new ConnectPoint(PHYDID3, PortNumber.portNumber(2));
+        manager.bindVirtualPort(virtualNetwork.id(), device2.id(),
+                                PortNumber.portNumber(1), newCp);
+        expectedEventTypes.add(DeviceEvent.Type.PORT_UPDATED);
+
+        manager.removeVirtualPort(virtualNetwork.id(),
+                                  (DeviceId) virtualPort.element().id(), virtualPort.number());
+        expectedEventTypes.add(DeviceEvent.Type.PORT_REMOVED);
+
+        // verify no virtual ports remain
+        virtualPorts = manager.getVirtualPorts(virtualNetwork.id(), device2.id());
+        assertTrue("The virtual port set should be empty.", virtualPorts.isEmpty());
+
+        // remove virtual device
+        manager.removeVirtualDevice(virtualNetwork.id(), device2.id());
+        expectedEventTypes.add(DeviceEvent.Type.DEVICE_REMOVED);
+
+        // Validate that the events were all received in the correct order.
+        validateEvents((Enum[]) expectedEventTypes.toArray(
+                new DeviceEvent.Type[expectedEventTypes.size()]));
+
+        // cleanup
+        deviceService.removeListener(testListener);
+    }
+
+    /**
      * Core service test class.
      */
     private class TestCoreService extends CoreServiceAdapter {
@@ -351,4 +447,35 @@
             };
         }
     }
+
+    /**
+     * Method to validate that the actual versus expected virtual network events were
+     * received correctly.
+     *
+     * @param types expected virtual network events.
+     */
+    private void validateEvents(Enum... types) {
+        TestTools.assertAfter(100, () -> {
+            int i = 0;
+            assertEquals("wrong events received", types.length, testListener.events.size());
+            for (Event event : testListener.events) {
+                assertEquals("incorrect event type", types[i], event.type());
+                i++;
+            }
+            testListener.events.clear();
+        });
+    }
+
+    /**
+     * Test listener class to receive device events.
+     */
+    private static class TestListener implements DeviceListener {
+
+        private List<DeviceEvent> events = Lists.newArrayList();
+
+        @Override
+        public void event(DeviceEvent event) {
+            events.add(event);
+        }
+    }
 }
diff --git a/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkFlowObjectiveManagerTest.java b/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkFlowObjectiveManagerTest.java
index 2ca243b..04e117f 100644
--- a/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkFlowObjectiveManagerTest.java
+++ b/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkFlowObjectiveManagerTest.java
@@ -33,8 +33,6 @@
 import org.onosproject.incubator.net.virtual.VirtualNetworkFlowObjectiveStore;
 import org.onosproject.incubator.net.virtual.VirtualNetworkFlowRuleStore;
 import org.onosproject.incubator.net.virtual.VirtualNetworkStore;
-import org.onosproject.incubator.net.virtual.event.VirtualEvent;
-import org.onosproject.incubator.net.virtual.event.VirtualListenerRegistryManager;
 import org.onosproject.incubator.net.virtual.impl.provider.VirtualProviderManager;
 import org.onosproject.incubator.net.virtual.provider.AbstractVirtualProvider;
 import org.onosproject.incubator.net.virtual.provider.VirtualFlowRuleProvider;
@@ -58,7 +56,7 @@
 import org.onosproject.store.service.StorageService;
 import org.onosproject.store.service.TestStorageService;
 
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
 
 /**
  * Junit tests for VirtualNetworkFlowObjectiveManager.
@@ -76,8 +74,6 @@
 
     private VirtualProviderManager providerRegistryService;
     private EventDeliveryService eventDeliveryService;
-    VirtualListenerRegistryManager listenerRegistryManager =
-            VirtualListenerRegistryManager.getInstance();
 
     private ApplicationId appId;
 
@@ -117,7 +113,6 @@
 
         eventDeliveryService = new TestEventDispatcher();
         NetTestTools.injectEventDispatcher(manager, eventDeliveryService);
-        eventDeliveryService.addSink(VirtualEvent.class, listenerRegistryManager);
 
         appId = new TestApplicationId("FlowRuleManagerTest");
 
diff --git a/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkFlowRuleManagerTest.java b/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkFlowRuleManagerTest.java
index fa93335..b1d7572 100644
--- a/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkFlowRuleManagerTest.java
+++ b/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkFlowRuleManagerTest.java
@@ -36,8 +36,6 @@
 import org.onosproject.incubator.net.virtual.VirtualNetwork;
 import org.onosproject.incubator.net.virtual.VirtualNetworkFlowRuleStore;
 import org.onosproject.incubator.net.virtual.VirtualNetworkStore;
-import org.onosproject.incubator.net.virtual.event.VirtualEvent;
-import org.onosproject.incubator.net.virtual.event.VirtualListenerRegistryManager;
 import org.onosproject.incubator.net.virtual.impl.provider.VirtualProviderManager;
 import org.onosproject.incubator.net.virtual.provider.AbstractVirtualProvider;
 import org.onosproject.incubator.net.virtual.provider.VirtualFlowRuleProvider;
@@ -87,8 +85,6 @@
     private VirtualProviderManager providerRegistryService;
 
     private EventDeliveryService eventDeliveryService;
-    VirtualListenerRegistryManager listenerRegistryManager =
-            VirtualListenerRegistryManager.getInstance();
 
     private VirtualNetworkFlowRuleManager vnetFlowRuleService1;
     private VirtualNetworkFlowRuleManager vnetFlowRuleService2;
@@ -126,7 +122,6 @@
 
         eventDeliveryService = new TestEventDispatcher();
         NetTestTools.injectEventDispatcher(manager, eventDeliveryService);
-        eventDeliveryService.addSink(VirtualEvent.class, listenerRegistryManager);
 
         appId = new TestApplicationId("FlowRuleManagerTest");
 
diff --git a/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkGroupManagerTest.java b/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkGroupManagerTest.java
index 8366fee..7034358 100644
--- a/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkGroupManagerTest.java
+++ b/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkGroupManagerTest.java
@@ -36,8 +36,6 @@
 import org.onosproject.incubator.net.virtual.VirtualNetwork;
 import org.onosproject.incubator.net.virtual.VirtualNetworkGroupStore;
 import org.onosproject.incubator.net.virtual.VirtualNetworkStore;
-import org.onosproject.incubator.net.virtual.event.VirtualEvent;
-import org.onosproject.incubator.net.virtual.event.VirtualListenerRegistryManager;
 import org.onosproject.incubator.net.virtual.impl.provider.VirtualProviderManager;
 import org.onosproject.incubator.net.virtual.provider.AbstractVirtualProvider;
 import org.onosproject.incubator.net.virtual.provider.VirtualGroupProvider;
@@ -89,8 +87,6 @@
     private VirtualProviderManager providerRegistryService;
 
     private EventDeliveryService eventDeliveryService;
-    VirtualListenerRegistryManager listenerRegistryManager =
-            VirtualListenerRegistryManager.getInstance();
 
     private VirtualNetworkGroupManager groupManager1;
     private VirtualNetworkGroupManager groupManager2;
@@ -130,7 +126,6 @@
 
         eventDeliveryService = new TestEventDispatcher();
         injectEventDispatcher(manager, eventDeliveryService);
-        eventDeliveryService.addSink(VirtualEvent.class, listenerRegistryManager);
 
         appId = new TestApplicationId("VirtualGroupManagerTest");
 
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 d3390a6..f525028 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
@@ -543,7 +543,7 @@
             virtualPortSet = new HashSet<>();
         }
 
-        Device device = deviceIdVirtualDeviceMap.get(deviceId);
+        VirtualDevice device = deviceIdVirtualDeviceMap.get(deviceId);
         checkNotNull(device, "The device has not been created for deviceId: " + deviceId);
 
         boolean exist = virtualPortSet.stream().anyMatch(
@@ -556,7 +556,7 @@
         virtualPortSet.add(virtualPort);
         networkIdVirtualPortSetMap.put(networkId, virtualPortSet);
         notifyDelegate(new VirtualNetworkEvent(VirtualNetworkEvent.Type.VIRTUAL_PORT_ADDED,
-                                               networkId, virtualPort));
+                                               networkId, device, virtualPort));
         return virtualPort;
     }
 
@@ -572,7 +572,7 @@
                         p.number().equals(portNumber)).findFirst().get();
         checkNotNull(vPort, "The virtual port has not been added.");
 
-        Device device = deviceIdVirtualDeviceMap.get(deviceId);
+        VirtualDevice device = deviceIdVirtualDeviceMap.get(deviceId);
         checkNotNull(device, "The device has not been created for deviceId: "
                 + deviceId);
 
@@ -581,12 +581,15 @@
         virtualPortSet.add(vPort);
         networkIdVirtualPortSetMap.put(networkId, virtualPortSet);
         notifyDelegate(new VirtualNetworkEvent(VirtualNetworkEvent.Type.VIRTUAL_PORT_UPDATED,
-                                               networkId, vPort));
+                                               networkId, device, vPort));
     }
 
     @Override
     public void removePort(NetworkId networkId, DeviceId deviceId, PortNumber portNumber) {
         checkState(networkExists(networkId), "The network has not been added.");
+        VirtualDevice device = deviceIdVirtualDeviceMap.get(deviceId);
+        checkNotNull(device, "The device has not been created for deviceId: "
+                + deviceId);
 
         Set<VirtualPort> virtualPortSet = new HashSet<>();
         networkIdVirtualPortSetMap.get(networkId).forEach(port -> {
@@ -608,7 +611,7 @@
             if (portRemoved.get()) {
                 virtualPortSet.forEach(virtualPort -> notifyDelegate(
                         new VirtualNetworkEvent(VirtualNetworkEvent.Type.VIRTUAL_PORT_REMOVED,
-                                                networkId, virtualPort)
+                                                networkId, device, virtualPort)
                 ));
             }
         }