diff --git a/src/main/java/net/floodlightcontroller/core/web/JacksonCustomConverter.java b/src/main/java/net/floodlightcontroller/core/web/JacksonCustomConverter.java index e8d76376c4fdfe0491154bf1722a12b1a23352df..9c45515a04e6ab588ad405b6a44e367f6d34b2d3 100644 --- a/src/main/java/net/floodlightcontroller/core/web/JacksonCustomConverter.java +++ b/src/main/java/net/floodlightcontroller/core/web/JacksonCustomConverter.java @@ -19,6 +19,9 @@ package net.floodlightcontroller.core.web; import java.util.List; +import net.floodlightcontroller.core.web.serializers.DeviceAttachmentPointJSONSerializer; +import net.floodlightcontroller.core.web.serializers.DeviceJSONSerializer; +import net.floodlightcontroller.core.web.serializers.DeviceNetworkAddressJSONSerializer; import net.floodlightcontroller.core.web.serializers.EventHistoryAttachmentPointJSONSerializer; import net.floodlightcontroller.core.web.serializers.EventHistoryBaseInfoJSONSerializer; import net.floodlightcontroller.core.web.serializers.EventHistoryTopologyClusterJSONSerializer; @@ -73,6 +76,9 @@ public class JacksonCustomConverter extends JacksonConverter { jsonModule.addSerializer(new EventHistoryTopologySwitchJSONSerializer()); jsonModule.addSerializer(new EventHistoryTopologyLinkJSONSerializer()); jsonModule.addSerializer(new EventHistoryTopologyClusterJSONSerializer()); + jsonModule.addSerializer(new DeviceJSONSerializer()); + jsonModule.addSerializer(new DeviceNetworkAddressJSONSerializer()); + jsonModule.addSerializer(new DeviceAttachmentPointJSONSerializer()); jsonObjectMapper.registerModule(jsonModule); } diff --git a/src/main/java/net/floodlightcontroller/core/web/serializers/DeviceAttachmentPointJSONSerializer.java b/src/main/java/net/floodlightcontroller/core/web/serializers/DeviceAttachmentPointJSONSerializer.java new file mode 100644 index 0000000000000000000000000000000000000000..7f9bd630b03eec933c1ba0dcbeac4ad7ae4ebb73 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/web/serializers/DeviceAttachmentPointJSONSerializer.java @@ -0,0 +1,27 @@ +package net.floodlightcontroller.core.web.serializers; + +import java.io.IOException; + +import net.floodlightcontroller.devicemanager.DeviceAttachmentPoint; + +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.map.JsonSerializer; +import org.codehaus.jackson.map.SerializerProvider; + +public class DeviceAttachmentPointJSONSerializer extends JsonSerializer<DeviceAttachmentPoint> { + @Override + public void serialize(DeviceAttachmentPoint dap, JsonGenerator jgen, SerializerProvider sp) + throws IOException, JsonProcessingException { + jgen.writeStartObject(); + jgen.writeStringField("switch", dap.getSwitchPort().getSw().getStringId()); + jgen.writeNumberField("port", dap.getSwitchPort().getPort()); + jgen.writeStringField("last-seen", dap.getLastSeen().toString()); + jgen.writeEndObject(); + } + + @Override + public Class<DeviceAttachmentPoint> handledType() { + return DeviceAttachmentPoint.class; + } +} diff --git a/src/main/java/net/floodlightcontroller/core/web/serializers/DeviceJSONSerializer.java b/src/main/java/net/floodlightcontroller/core/web/serializers/DeviceJSONSerializer.java new file mode 100644 index 0000000000000000000000000000000000000000..c2c0eb53f0883058a634d0355950f1fe2cbb232f --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/web/serializers/DeviceJSONSerializer.java @@ -0,0 +1,42 @@ +package net.floodlightcontroller.core.web.serializers; + +import java.io.IOException; + +import net.floodlightcontroller.devicemanager.Device; +import net.floodlightcontroller.devicemanager.DeviceAttachmentPoint; +import net.floodlightcontroller.devicemanager.DeviceNetworkAddress; + +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.map.JsonSerializer; +import org.codehaus.jackson.map.SerializerProvider; + +public class DeviceJSONSerializer extends JsonSerializer<Device> { + + @Override + public void serialize(Device device, JsonGenerator jgen, SerializerProvider sp) + throws IOException, JsonProcessingException { + jgen.writeStartObject(); + jgen.writeStringField("last-seen", device.getLastSeen().toString()); + if (device.getVlanId() != null) + jgen.writeNumberField("vlan", device.getVlanId()); + else + jgen.writeNullField("vlan"); + jgen.writeArrayFieldStart("network-addresses"); + for (DeviceNetworkAddress dna : device.getNetworkAddresses()) { + sp.defaultSerializeValue(dna, jgen); + } + jgen.writeEndArray(); + jgen.writeArrayFieldStart("attachment-points"); + for (DeviceAttachmentPoint dap : device.getAttachmentPoints()) { + sp.defaultSerializeValue(dap, jgen); + } + jgen.writeEndArray(); + jgen.writeEndObject(); + } + + @Override + public Class<Device> handledType() { + return Device.class; + } +} diff --git a/src/main/java/net/floodlightcontroller/core/web/serializers/DeviceNetworkAddressJSONSerializer.java b/src/main/java/net/floodlightcontroller/core/web/serializers/DeviceNetworkAddressJSONSerializer.java new file mode 100644 index 0000000000000000000000000000000000000000..fb4c0ce9914770fb61e5ba274625cf0ad6c47109 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/web/serializers/DeviceNetworkAddressJSONSerializer.java @@ -0,0 +1,28 @@ +package net.floodlightcontroller.core.web.serializers; + +import java.io.IOException; + +import net.floodlightcontroller.devicemanager.DeviceNetworkAddress; +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; + +public class DeviceNetworkAddressJSONSerializer extends JsonSerializer<DeviceNetworkAddress> { + + @Override + public void serialize(DeviceNetworkAddress dna, JsonGenerator jgen, SerializerProvider sp) + throws IOException, JsonProcessingException { + jgen.writeStartObject(); + jgen.writeStringField("ip", IPv4.fromIPv4Address(dna.getNetworkAddress())); + jgen.writeStringField("last-seen", dna.getLastSeen().toString()); + jgen.writeEndObject(); + } + + @Override + public Class<DeviceNetworkAddress> handledType() { + return DeviceNetworkAddress.class; + } +} diff --git a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java index 0ef75af5c303218a3ceca7baf54e823f0c4e04d8..8417420ebef9ef688fb18224d18a76e989fa5dda 100755 --- a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java +++ b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java @@ -59,6 +59,7 @@ import net.floodlightcontroller.linkdiscovery.SwitchPortTuple; import net.floodlightcontroller.packet.ARP; import net.floodlightcontroller.packet.Ethernet; import net.floodlightcontroller.packet.IPv4; +import net.floodlightcontroller.restserver.IRestApiService; import net.floodlightcontroller.routing.ForwardingBase; import net.floodlightcontroller.storage.IResultSet; import net.floodlightcontroller.storage.IStorageSourceListener; @@ -631,6 +632,7 @@ public class DeviceManagerImpl implements IDeviceManagerService, IOFMessageListe protected ITopologyService topology; protected IStorageSourceService storageSource; protected IThreadPoolService threadPool; + protected IRestApiService restApi; protected Runnable deviceAgingTimer; protected SingletonTask deviceUpdateTask; @@ -2072,6 +2074,7 @@ public class DeviceManagerImpl implements IDeviceManagerService, IOFMessageListe l.add(ILinkDiscoveryService.class); l.add(IStorageSourceService.class); l.add(IThreadPoolService.class); + l.add(IRestApiService.class); return l; } @@ -2089,6 +2092,8 @@ public class DeviceManagerImpl implements IDeviceManagerService, IOFMessageListe context.getServiceImpl(IStorageSourceService.class); threadPool = context.getServiceImpl(IThreadPoolService.class); + restApi = + context.getServiceImpl(IRestApiService.class); // We create this here because there is no ordering guarantee this.deviceManagerAware = new HashSet<IDeviceManagerAware>(); @@ -2143,6 +2148,9 @@ public class DeviceManagerImpl implements IDeviceManagerService, IOFMessageListe floodlightProvider.addOFSwitchListener(this); floodlightProvider.addInfoProvider("summary", this); + // Register our REST API + restApi.addRestletRoutable(new DeviceManagerWebRoutable()); + // Read all our device state (MACs, IPs, attachment points) from storage readAllDeviceStateFromStorage(); // Device and storage aging. diff --git a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerWebRoutable.java b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerWebRoutable.java new file mode 100644 index 0000000000000000000000000000000000000000..cc87b3944efbd57b7c54b15f96a25f846c1ef0bd --- /dev/null +++ b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerWebRoutable.java @@ -0,0 +1,27 @@ +package net.floodlightcontroller.devicemanager.internal; + +import org.restlet.Context; +import org.restlet.Restlet; +import org.restlet.routing.Router; + +import net.floodlightcontroller.restserver.RestletRoutable; + +/** + * Restlet Routable to handle DeviceManager API + * @author alexreimers + * + */ +public class DeviceManagerWebRoutable implements RestletRoutable { + + @Override + public Restlet getRestlet(Context context) { + Router router = new Router(context); + router.attach("/device/{device}/json", DeviceResource.class); + return router; + } + + @Override + public String basePath() { + return "/wm/devicemanager"; + } +} diff --git a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceResource.java b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceResource.java new file mode 100644 index 0000000000000000000000000000000000000000..fa1cfce11f7ecc89b97c9da9a4adc17c329fdf7e --- /dev/null +++ b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceResource.java @@ -0,0 +1,45 @@ +package net.floodlightcontroller.devicemanager.internal; + +import java.util.HashMap; +import java.util.Map; + +import net.floodlightcontroller.devicemanager.Device; +import net.floodlightcontroller.devicemanager.IDeviceManagerService; + +import org.openflow.util.HexString; +import org.restlet.resource.Get; +import org.restlet.resource.ServerResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class DeviceResource extends ServerResource { + protected static Logger log = + LoggerFactory.getLogger(DeviceResource.class); + + @Get("json") + public Map<String, Device> retrieve() { + Map<String, Device> retMap = new HashMap<String, Device>(); + IDeviceManagerService dm = + (IDeviceManagerService)getContext().getAttributes(). + get(IDeviceManagerService.class.getCanonicalName()); + + String param = (String) getRequestAttributes().get("device"); + + if (param.toLowerCase().equals("all")) { + // Get all devices + for (Device d : dm.getDevices()) { + retMap.put(HexString.toHexString(d.getDataLayerAddress()), d); + } + } else { + // Get device by MAC + Device dev = null; + byte[] devMac = HexString.fromHexString(param); + dev = dm.getDeviceByDataLayerAddress(devMac); + if (dev != null) { + retMap.put(HexString.toHexString(dev.getDataLayerAddress()), dev); + } + } + + return retMap; + } +}