From bf51f8202f4518087bc086e77ff558fe08982532 Mon Sep 17 00:00:00 2001
From: Rob Adams <rob.adams@bigswitch.com>
Date: Tue, 13 Mar 2012 18:10:42 -0700
Subject: [PATCH] Add device service rest API

---
 .../devicemanager/internal/Device.java        |   3 +
 .../internal/DeviceManagerImpl.java           |  59 ++-------
 .../web/AbstractDeviceResource.java           | 124 ++++++++++++++++++
 .../devicemanager/web/DeviceResource.java     |  47 +++++++
 .../devicemanager/web/DeviceRoutable.java     |  43 ++++++
 .../devicemanager/web/DeviceSerializer.java   |  70 ++++++++++
 .../restserver/RestApiServer.java             |  13 ++
 .../internal/DeviceManagerImplTest.java       |  58 --------
 8 files changed, 313 insertions(+), 104 deletions(-)
 create mode 100644 src/main/java/net/floodlightcontroller/devicemanager/web/AbstractDeviceResource.java
 create mode 100644 src/main/java/net/floodlightcontroller/devicemanager/web/DeviceResource.java
 create mode 100644 src/main/java/net/floodlightcontroller/devicemanager/web/DeviceRoutable.java
 create mode 100644 src/main/java/net/floodlightcontroller/devicemanager/web/DeviceSerializer.java

diff --git a/src/main/java/net/floodlightcontroller/devicemanager/internal/Device.java b/src/main/java/net/floodlightcontroller/devicemanager/internal/Device.java
index 0952eeed4..22b7ed23a 100755
--- a/src/main/java/net/floodlightcontroller/devicemanager/internal/Device.java
+++ b/src/main/java/net/floodlightcontroller/devicemanager/internal/Device.java
@@ -25,9 +25,11 @@ import java.util.EnumSet;
 import java.util.Iterator;
 import java.util.TreeSet;
 
+import org.codehaus.jackson.map.annotate.JsonSerialize;
 import org.openflow.util.HexString;
 
 import net.floodlightcontroller.devicemanager.IDeviceService.DeviceField;
+import net.floodlightcontroller.devicemanager.web.DeviceSerializer;
 import net.floodlightcontroller.devicemanager.IDevice;
 import net.floodlightcontroller.devicemanager.IEntityClass;
 import net.floodlightcontroller.devicemanager.SwitchPort;
@@ -37,6 +39,7 @@ import net.floodlightcontroller.topology.ITopologyService;
  * Concrete implementation of {@link IDevice}
  * @author readams
  */
+@JsonSerialize(using=DeviceSerializer.class)
 public class Device implements IDevice {
     protected Long deviceKey;
     protected DeviceManagerImpl deviceManager;
diff --git a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java
index b506ccdd0..5a5e8a54b 100755
--- a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java
+++ b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java
@@ -41,7 +41,6 @@ import net.floodlightcontroller.core.IFloodlightProviderService;
 import net.floodlightcontroller.core.IInfoProvider;
 import net.floodlightcontroller.core.IOFMessageListener;
 import net.floodlightcontroller.core.IOFSwitch;
-import net.floodlightcontroller.core.IOFSwitchListener;
 import net.floodlightcontroller.core.module.FloodlightModuleContext;
 import net.floodlightcontroller.core.module.IFloodlightModule;
 import net.floodlightcontroller.core.module.IFloodlightService;
@@ -51,15 +50,16 @@ import net.floodlightcontroller.devicemanager.IDeviceService;
 import net.floodlightcontroller.devicemanager.IEntityClass;
 import net.floodlightcontroller.devicemanager.IEntityClassifier;
 import net.floodlightcontroller.devicemanager.IDeviceListener;
+import net.floodlightcontroller.devicemanager.web.DeviceRoutable;
 import net.floodlightcontroller.packet.ARP;
 import net.floodlightcontroller.packet.DHCP;
 import net.floodlightcontroller.packet.Ethernet;
 import net.floodlightcontroller.packet.IPv4;
 import net.floodlightcontroller.packet.UDP;
+import net.floodlightcontroller.restserver.IRestApiService;
 import net.floodlightcontroller.storage.IStorageSourceService;
 import net.floodlightcontroller.storage.IStorageSourceListener;
 import net.floodlightcontroller.topology.ITopologyService;
-import net.floodlightcontroller.topology.ITopologyListener;
 import net.floodlightcontroller.util.MultiIterator;
 import static net.floodlightcontroller.devicemanager.internal.
             DeviceManagerImpl.DeviceUpdate.Change.*;
@@ -67,7 +67,6 @@ import static net.floodlightcontroller.devicemanager.internal.
 import org.openflow.protocol.OFMessage;
 import org.openflow.protocol.OFPacketIn;
 import org.openflow.protocol.OFPhysicalPort;
-import org.openflow.protocol.OFPortStatus;
 import org.openflow.protocol.OFType;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -80,7 +79,6 @@ import org.slf4j.LoggerFactory;
  */
 public class DeviceManagerImpl implements 
         IDeviceService, IOFMessageListener,
-        IOFSwitchListener, ITopologyListener, 
         IStorageSourceListener, IFloodlightModule,
         IInfoProvider {  
     protected static Logger logger = 
@@ -89,6 +87,7 @@ public class DeviceManagerImpl implements
     protected IFloodlightProviderService floodlightProvider;
     protected ITopologyService topology;
     protected IStorageSourceService storageSource;
+    protected IRestApiService restApi;
     
     /**
      * Time in milliseconds before entities will expire
@@ -436,9 +435,6 @@ public class DeviceManagerImpl implements
             case PACKET_IN:
                 return this.processPacketInMessage(sw, 
                                                    (OFPacketIn) msg, cntx);
-            case PORT_STATUS:
-                return this.processPortStatusMessage(sw, 
-                                                     (OFPortStatus) msg);
         }
 
         logger.error("received an unexpected message {} from switch {}", 
@@ -462,31 +458,6 @@ public class DeviceManagerImpl implements
         
     }
 
-    // *****************
-    // ITopologyListener
-    // *****************
-
-    @Override
-    public void toplogyChanged() {
-        // TODO Auto-generated method stub
-        
-    }
-    
-    // *****************
-    // IOFSwitchListener
-    // *****************
-
-    @Override
-    public void addedSwitch(IOFSwitch sw) {
-        // TODO Auto-generated method stub
-        
-    }
-
-    @Override
-    public void removedSwitch(IOFSwitch sw) {
-        // TODO Auto-generated method stub
-    }
-
     // *****************
     // IFloodlightModule
     // *****************
@@ -518,6 +489,7 @@ public class DeviceManagerImpl implements
         l.add(IFloodlightProviderService.class);
         l.add(IStorageSourceService.class);
         l.add(ITopologyService.class);
+        l.add(IRestApiService.class);
         return l;
     }
 
@@ -535,6 +507,8 @@ public class DeviceManagerImpl implements
                 fmc.getServiceImpl(IStorageSourceService.class);
         this.topology =
                 fmc.getServiceImpl(ITopologyService.class);
+        this.restApi = fmc.getServiceImpl(IRestApiService.class);
+
     }
     
     @Override
@@ -580,17 +554,8 @@ public class DeviceManagerImpl implements
                 return r;
             }
         };
-
-        if (topology != null) {
-            // Register to get updates from topology
-            topology.addListener(this);
-        } else {
-            logger.error("Could not add topology listener");
-        }
         
         floodlightProvider.addOFMessageListener(OFType.PACKET_IN, this);
-        floodlightProvider.addOFMessageListener(OFType.PORT_STATUS, this);
-        floodlightProvider.addOFSwitchListener(this);
         
         Runnable ecr = new Runnable() {
             @Override
@@ -605,16 +570,17 @@ public class DeviceManagerImpl implements
         entityCleanupTask = new SingletonTask(ses, ecr);
         entityCleanupTask.reschedule(ENTITY_CLEANUP_INTERVAL, 
                                      TimeUnit.SECONDS);
+        
+        if (restApi != null) {
+            restApi.addRestletRoutable(new DeviceRoutable());
+        } else {
+            logger.error("Could not instantiate REST API");
+        }
     }
     
     // ****************
     // Internal methods
     // ****************
-    
-    protected Command processPortStatusMessage(IOFSwitch sw, OFPortStatus ps) {
-        // XXX - TODO
-        return null;        
-    }
 
     /**
      * This method is called for every packet-in and should be optimized for
@@ -1045,6 +1011,7 @@ public class DeviceManagerImpl implements
                         break;
                     case DELETE:
                         listener.deviceRemoved(update.device);
+                        break;
                     case CHANGE:
                         for (DeviceField field : update.fieldsChanged) {
                             switch (field) {
diff --git a/src/main/java/net/floodlightcontroller/devicemanager/web/AbstractDeviceResource.java b/src/main/java/net/floodlightcontroller/devicemanager/web/AbstractDeviceResource.java
new file mode 100644
index 000000000..67a9db18d
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/devicemanager/web/AbstractDeviceResource.java
@@ -0,0 +1,124 @@
+/**
+*    Copyright 2012, Big Switch Networks, Inc. 
+*    Originally created by David Erickson, Stanford University
+* 
+*    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 net.floodlightcontroller.devicemanager.web;
+
+import java.util.Iterator;
+
+import net.floodlightcontroller.devicemanager.IDevice;
+import net.floodlightcontroller.devicemanager.IDeviceService;
+import net.floodlightcontroller.packet.IPv4;
+
+import org.openflow.util.HexString;
+import org.restlet.data.Form;
+import org.restlet.data.Status;
+import org.restlet.resource.ServerResource;
+
+/**
+ * Resource for querying and displaying devices that exist in the system
+ */
+public abstract class AbstractDeviceResource extends ServerResource {
+    public static final String MAC_ERROR = 
+            "Invalid MAC address: must be a 48-bit quantity, " + 
+            "expressed in hex as AA:BB:CC:DD:EE:FF";
+    public static final String VLAN_ERROR = 
+            "Invalid VLAN: must be an integer in the range 0-4095";
+    public static final String IPV4_ERROR = 
+            "Invalid IPv4 address: must be in dotted decimal format, " + 
+            "234.0.59.1";
+    public static final String DPID_ERROR = 
+            "Invalid Switch DPID: must be a 64-bit quantity, expressed in " + 
+            "hex as AA:BB:CC:DD:EE:FF:00:11";
+    public static final String PORT_ERROR = 
+            "Invalid Port: must be a positive integer";
+    
+    public Iterator<? extends IDevice> getDevices() {
+        IDeviceService deviceManager = 
+                (IDeviceService)getContext().getAttributes().
+                    get(IDeviceService.class.getCanonicalName());  
+                
+        Long macAddress = null;
+        Short vlan = null;
+        Integer ipv4Address = null;
+        Long switchDPID = null;
+        Integer switchPort = null;
+        
+        Form form = getQuery();
+        String macAddrStr = form.getFirstValue("mac", true);
+        String vlanStr = form.getFirstValue("vlan", true);
+        String ipv4Str = form.getFirstValue("ipv4", true);
+        String dpid = form.getFirstValue("dpid", true);
+        String port = form.getFirstValue("port", true);
+        
+        if (macAddrStr != null) {
+            try {
+                macAddress = HexString.toLong(macAddrStr);
+            } catch (Exception e) {
+                setStatus(Status.CLIENT_ERROR_BAD_REQUEST, MAC_ERROR);
+                return null;
+            }
+        }
+        if (vlanStr != null) {
+            try {
+                vlan = Short.parseShort(vlanStr);
+                if (vlan > 4095 || vlan < 0) {
+                    setStatus(Status.CLIENT_ERROR_BAD_REQUEST, VLAN_ERROR);
+                    return null;
+                }
+            } catch (Exception e) {
+                setStatus(Status.CLIENT_ERROR_BAD_REQUEST, VLAN_ERROR);
+                return null;
+            }
+        }
+        if (ipv4Str != null) {
+            try {
+                ipv4Address = IPv4.toIPv4Address(ipv4Str);
+            } catch (Exception e) {
+                setStatus(Status.CLIENT_ERROR_BAD_REQUEST, IPV4_ERROR);
+                return null;
+            }
+        }
+        if (dpid != null) {
+            try {
+                switchDPID = HexString.toLong(dpid);
+            } catch (Exception e) {
+                setStatus(Status.CLIENT_ERROR_BAD_REQUEST, DPID_ERROR);
+                return null;
+            }
+        }
+        if (port != null) {
+            try {
+                switchPort = Integer.parseInt(port);
+                if (switchPort < 0) {
+                    setStatus(Status.CLIENT_ERROR_BAD_REQUEST, PORT_ERROR);
+                    return null;
+                }
+            } catch (Exception e) {
+                setStatus(Status.CLIENT_ERROR_BAD_REQUEST, PORT_ERROR);
+                return null;
+            }
+        }
+        
+        Iterator<? extends IDevice> diter =
+                deviceManager.queryDevices(macAddress, 
+                                           vlan, 
+                                           ipv4Address, 
+                                           switchDPID, 
+                                           switchPort);
+        return diter;
+    }
+}
diff --git a/src/main/java/net/floodlightcontroller/devicemanager/web/DeviceResource.java b/src/main/java/net/floodlightcontroller/devicemanager/web/DeviceResource.java
new file mode 100644
index 000000000..1139d68d0
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/devicemanager/web/DeviceResource.java
@@ -0,0 +1,47 @@
+/**
+*    Copyright 2012, Big Switch Networks, Inc. 
+*    Originally created by David Erickson, Stanford University
+* 
+*    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 net.floodlightcontroller.devicemanager.web;
+
+import java.util.Iterator;
+
+import net.floodlightcontroller.devicemanager.IDevice;
+import org.restlet.resource.Get;
+
+/**
+ * Resource for querying and displaying devices that exist in the system
+ */
+public class DeviceResource extends AbstractDeviceResource {
+    public static final String MAC_ERROR = 
+            "Invalid MAC address: must be a 48-bit quantity, " + 
+            "expressed in hex as AA:BB:CC:DD:EE:FF";
+    public static final String VLAN_ERROR = 
+            "Invalid VLAN: must be an integer in the range 0-4095";
+    public static final String IPV4_ERROR = 
+            "Invalid IPv4 address: must be in dotted decimal format, " + 
+            "234.0.59.1";
+    public static final String DPID_ERROR = 
+            "Invalid Switch DPID: must be a 64-bit quantity, expressed in " + 
+            "hex as AA:BB:CC:DD:EE:FF:00:11";
+    public static final String PORT_ERROR = 
+            "Invalid Port: must be a positive integer";
+    
+    @Get("json")
+    public Iterator<? extends IDevice> getDevices() {
+        return super.getDevices();
+    }
+}
diff --git a/src/main/java/net/floodlightcontroller/devicemanager/web/DeviceRoutable.java b/src/main/java/net/floodlightcontroller/devicemanager/web/DeviceRoutable.java
new file mode 100644
index 000000000..3dea45c8a
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/devicemanager/web/DeviceRoutable.java
@@ -0,0 +1,43 @@
+/**
+*    Copyright 2012, Big Switch Networks, Inc. 
+*    Originally created by David Erickson, Stanford University
+* 
+*    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 net.floodlightcontroller.devicemanager.web;
+
+import org.restlet.Context;
+import org.restlet.Restlet;
+import org.restlet.routing.Router;
+
+import net.floodlightcontroller.restserver.RestletRoutable;
+
+/**
+ * Routable for device rest api
+ */
+public class DeviceRoutable implements RestletRoutable {
+
+    @Override
+    public String basePath() {
+        return "/wm/device";
+    }
+    
+    @Override
+    public Restlet getRestlet(Context context) {
+        Router router = new Router(context);
+        router.attach("/", DeviceResource.class);
+        return router;
+    }
+
+}
diff --git a/src/main/java/net/floodlightcontroller/devicemanager/web/DeviceSerializer.java b/src/main/java/net/floodlightcontroller/devicemanager/web/DeviceSerializer.java
new file mode 100644
index 000000000..fe93761e2
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/devicemanager/web/DeviceSerializer.java
@@ -0,0 +1,70 @@
+/**
+*    Copyright 2012 Big Switch Networks, Inc. 
+*    Originally created by David Erickson, Stanford University
+* 
+*    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 net.floodlightcontroller.devicemanager.web;
+
+import java.io.IOException;
+
+import net.floodlightcontroller.devicemanager.SwitchPort;
+import net.floodlightcontroller.devicemanager.internal.Device;
+import net.floodlightcontroller.packet.IPv4;
+
+import org.codehaus.jackson.JsonGenerator;
+import org.codehaus.jackson.JsonProcessingException;
+import org.codehaus.jackson.map.JsonSerializer;
+import org.codehaus.jackson.map.SerializerProvider;
+import org.openflow.util.HexString;
+
+/**
+ * Serialize a device object
+ */
+public class DeviceSerializer extends JsonSerializer<Device> {
+
+    @Override
+    public void serialize(Device device, JsonGenerator jGen,
+                          SerializerProvider serializer) throws IOException,
+            JsonProcessingException {
+        jGen.writeStartObject();
+        
+        jGen.writeArrayFieldStart("mac");
+        jGen.writeString(HexString.toHexString(device.getMACAddress(), 6));
+        jGen.writeEndArray();
+
+        jGen.writeArrayFieldStart("ipv4");
+        for (Integer ip : device.getIPv4Addresses())
+            jGen.writeString(IPv4.fromIPv4Address(ip));
+        jGen.writeEndArray();
+
+        jGen.writeArrayFieldStart("vlan");
+        for (Short ip : device.getVlanId())
+            if (ip >= 0)
+                jGen.writeNumber(ip);
+        jGen.writeEndArray();
+        jGen.writeArrayFieldStart("attachmentPoint");
+        for (SwitchPort ap : device.getAttachmentPoints()) {
+            jGen.writeStartObject();
+            jGen.writeStringField("dpid", 
+                                  HexString.toHexString(ap.getSwitchDPID(), 8));
+            jGen.writeNumberField("port", ap.getPort());
+            jGen.writeEndObject();
+        }
+        jGen.writeEndArray();
+
+        jGen.writeEndObject();
+    }
+
+}
diff --git a/src/main/java/net/floodlightcontroller/restserver/RestApiServer.java b/src/main/java/net/floodlightcontroller/restserver/RestApiServer.java
index f4071c824..1588df22d 100644
--- a/src/main/java/net/floodlightcontroller/restserver/RestApiServer.java
+++ b/src/main/java/net/floodlightcontroller/restserver/RestApiServer.java
@@ -14,9 +14,13 @@ import org.restlet.Response;
 import org.restlet.Restlet;
 import org.restlet.data.Protocol;
 import org.restlet.data.Reference;
+import org.restlet.data.Status;
+import org.restlet.ext.jackson.JacksonRepresentation;
+import org.restlet.representation.Representation;
 import org.restlet.routing.Filter;
 import org.restlet.routing.Router;
 import org.restlet.routing.Template;
+import org.restlet.service.StatusService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -73,6 +77,15 @@ public class RestApiServer
         }
         
         public void run(FloodlightModuleContext fmlContext, int restPort) {
+            setStatusService(new StatusService() {
+                @Override
+                public Representation getRepresentation(Status status,
+                                                        Request request,
+                                                        Response response) {
+                    return new JacksonRepresentation<Status>(status);
+                }                
+            });
+            
             // Add everything in the module context to the rest
             for (Class<? extends IFloodlightService> s : fmlContext.getAllServices()) {
                 context.getAttributes().put(s.getCanonicalName(), 
diff --git a/src/test/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImplTest.java b/src/test/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImplTest.java
index 989de4741..c7fd7fe1d 100644
--- a/src/test/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImplTest.java
+++ b/src/test/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImplTest.java
@@ -632,62 +632,4 @@ public class DeviceManagerImplTest extends FloodlightTestCase {
         deviceManager.readPortChannelConfigFromStorage();
     }
     */
-    /**
-     * The same test as testAttachmentPointFlapping except for port-channel
-     * @throws Exception
-     */
-    @Test
-    public void testPortChannel() throws Exception {
-        fail();
-        /*
-    	OFPhysicalPort port1 = new OFPhysicalPort();
-    	OFPhysicalPort port2 = new OFPhysicalPort();
-        port1.setName("port1");
-        port2.setName("port2");
-
-        setupPortChannel();
-        byte[] dataLayerSource = ((Ethernet)this.testPacket).getSourceMACAddress();
-
-        // Mock up our expected behavior
-        IOFSwitch mockSwitch = createMock(IOFSwitch.class);
-        expect(mockSwitch.getPort((short)1)).andReturn(port1).anyTimes();
-        expect(mockSwitch.getPort((short)2)).andReturn(port2).anyTimes();
-        expect(mockSwitch.getId()).andReturn(1L).anyTimes();
-        expect(mockSwitch.getStringId()).andReturn("00:00:00:00:00:00:00:01").anyTimes();
-        ITopologyService mockTopology = createMock(ITopologyService.class);
-        expect(mockTopology.isInternal(1L, (short)1))
-                           .andReturn(false).atLeastOnce();
-        expect(mockTopology.isInternal(1L, (short)2))
-                           .andReturn(false).atLeastOnce();
-        deviceManager.setTopology(mockTopology);
-
-        // Start recording the replay on the mocks
-        replay(mockSwitch, mockTopology);
-
-        // Get the listener and trigger the packet in
-        mockFloodlightProvider.dispatchMessage(mockSwitch, this.packetIn);
-        mockFloodlightProvider.dispatchMessage(mockSwitch, this.packetIn.setInPort((short)2));
-        mockFloodlightProvider.dispatchMessage(mockSwitch, this.packetIn.setInPort((short)1));
-        mockFloodlightProvider.dispatchMessage(mockSwitch, this.packetIn.setInPort((short)2));
-        mockFloodlightProvider.dispatchMessage(mockSwitch, this.packetIn.setInPort((short)1));
-        mockFloodlightProvider.dispatchMessage(mockSwitch, this.packetIn.setInPort((short)2));
-
-        Device device = deviceManager.getDeviceByDataLayerAddress(dataLayerSource);
-        
-        // Verify the replay matched our expectations
-        verify(mockSwitch, mockTopology);
-
-        // Verify the device
-        assertEquals(device.getAttachmentPoints().size(), 1);
-        assertEquals(device.getOldAttachmentPoints().size(), 1);
-        for (DeviceAttachmentPoint ap : device.getOldAttachmentPoints()) {
-            assertFalse(ap.isBlocked());
-        }
-        
-        // Reset the device cache
-        deviceManager.clearAllDeviceStateFromMemory();
-        
-        teardownPortChannel();
-        */
-    }
 }
-- 
GitLab