Simon Hunt

Started fleshing out the UI topo model classes.

If reviewing this, please refer to http://tinyurl.com/onos-ui-topo-model

Change-Id: I4738392bec1a89c37dff15eff6fe04d66fcabd95
......@@ -16,8 +16,20 @@
package org.onosproject.ui.model.topo;
import java.util.ArrayList;
import java.util.List;
/**
* Encapsulates the notion of the ONOS cluster.
*/
public class UiCluster extends UiElement {
class UiCluster extends UiElement {
private final List<UiClusterMember> members = new ArrayList<>();
/**
* Removes all cluster members.
*/
void clear() {
members.clear();
}
}
......
......@@ -16,8 +16,17 @@
package org.onosproject.ui.model.topo;
import org.onosproject.net.Device;
/**
* Represents a device.
*/
public class UiDevice extends UiNode {
private Device device;
@Override
protected void destroy() {
device = null;
}
}
......
......@@ -20,4 +20,12 @@ package org.onosproject.ui.model.topo;
* Abstract base class of all elements in the UI topology model.
*/
public class UiElement {
/**
* Removes all external references, and prepares the instance for
* garbage collection. This default implementation does nothing.
*/
protected void destroy() {
// does nothing
}
}
......
......@@ -16,8 +16,17 @@
package org.onosproject.ui.model.topo;
import org.onosproject.net.Host;
/**
* Represents an end-station host.
*/
public class UiHost extends UiNode {
private Host host;
@Override
protected void destroy() {
host = null;
}
}
......
......@@ -16,8 +16,42 @@
package org.onosproject.ui.model.topo;
import org.onosproject.net.Device;
import org.onosproject.net.EdgeLink;
import org.onosproject.net.Link;
import java.util.Set;
/**
* Represents a bi-directional link backed by two uni-directional links.
*/
public class UiLink extends UiElement {
// devices at either end of this link
private Device deviceA;
private Device deviceB;
// two unidirectional links underlying this link...
private Link linkAtoB;
private Link linkBtoA;
// ==OR== : private (synthetic) host link
private EdgeLink edgeLink;
// ==OR== : set of underlying UI links that this link aggregates
private Set<UiLink> children;
@Override
protected void destroy() {
deviceA = null;
deviceB = null;
linkAtoB = null;
linkBtoA = null;
edgeLink = null;
if (children != null) {
children.clear();
children = null;
}
}
}
......
......@@ -19,5 +19,5 @@ package org.onosproject.ui.model.topo;
/**
* Represents a node drawn on the topology view (region, device, host).
*/
public abstract class UiNode extends UiElement {
abstract class UiNode extends UiElement {
}
......
......@@ -16,8 +16,34 @@
package org.onosproject.ui.model.topo;
import org.onosproject.net.region.Region;
import java.util.Set;
import java.util.TreeSet;
/**
* Represents a region.
*/
public class UiRegion extends UiNode {
private final Set<UiDevice> uiDevices = new TreeSet<>();
private final Set<UiHost> uiHosts = new TreeSet<>();
private final Set<UiLink> uiLinks = new TreeSet<>();
private Region region;
@Override
protected void destroy() {
uiDevices.forEach(UiDevice::destroy);
uiHosts.forEach(UiHost::destroy);
uiLinks.forEach(UiLink::destroy);
uiDevices.clear();
uiHosts.clear();
uiLinks.clear();
region = null;
}
}
......
......@@ -16,8 +16,29 @@
package org.onosproject.ui.model.topo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Set;
import java.util.TreeSet;
/**
* Represents the overall network topology.
*/
public class UiTopology extends UiElement {
private static final Logger log = LoggerFactory.getLogger(UiTopology.class);
private final UiCluster uiCluster = new UiCluster();
private final Set<UiRegion> uiRegions = new TreeSet<>();
/**
* Clears the topology state; that is, drops all regions, devices, hosts,
* links, and cluster members.
*/
public void clear() {
log.debug("clearing topology model");
uiRegions.clear();
uiCluster.clear();
}
}
......
......@@ -16,9 +16,19 @@
package org.onosproject.ui.impl.topo.model;
import org.onosproject.cluster.ControllerNode;
import org.onosproject.cluster.RoleInfo;
import org.onosproject.event.EventDispatcher;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Host;
import org.onosproject.net.Link;
import org.onosproject.net.region.Region;
import org.onosproject.ui.model.topo.UiDevice;
import org.onosproject.ui.model.topo.UiTopology;
import static org.onosproject.ui.impl.topo.model.UiModelEvent.Type.DEVICE_ADDED;
import static org.onosproject.ui.impl.topo.model.UiModelEvent.Type.DEVICE_REMOVED;
/**
* UI Topology Model cache.
......@@ -26,6 +36,7 @@ import org.onosproject.ui.model.topo.UiDevice;
class ModelCache {
private final EventDispatcher dispatcher;
private final UiTopology uiTopology = new UiTopology();
ModelCache(EventDispatcher eventDispatcher) {
this.dispatcher = eventDispatcher;
......@@ -35,7 +46,7 @@ class ModelCache {
* Clear our model.
*/
void clear() {
// TODO: clear our internal state
uiTopology.clear();
}
/**
......@@ -50,26 +61,72 @@ class ModelCache {
}
// add or update device
void addOrUpdateDevice(Device device) {
// fetch UiDevice
// TODO: find or create device assoc. with parameter
// FIXME
UiDevice uiDevice = new UiDevice();
dispatcher.post(
new UiModelEvent(UiModelEvent.Type.DEVICE_ADDED, uiDevice)
);
// TODO: post the (correct) event
dispatcher.post(new UiModelEvent(DEVICE_ADDED, uiDevice));
}
void removeDevice(Device device) {
// TODO: get UiDevice associated with the given parameter; remove from model
// FIXME
UiDevice uiDevice = new UiDevice();
dispatcher.post(
new UiModelEvent(UiModelEvent.Type.DEVICE_REMOVED, uiDevice)
);
// TODO: post the (correct) event
dispatcher.post(new UiModelEvent(DEVICE_REMOVED, uiDevice));
}
void addOrUpdateClusterMember(ControllerNode cnode) {
// TODO: find or create cluster member assoc. with parameter
// TODO: post event
}
void removeClusterMember(ControllerNode cnode) {
// TODO: find cluster member assoc. with parameter; remove from model
// TODO: post event
}
// TODO remaining model objects
void updateMasterships(DeviceId deviceId, RoleInfo roleInfo) {
// TODO: store the updated mastership information
// TODO: post event
}
void addOrUpdateRegion(Region region) {
// TODO: find or create region assoc. with parameter
// TODO: post event
}
void removeRegion(Region region) {
// TODO: find region assoc. with parameter; remove from model
// TODO: post event
}
void addOrUpdateLink(Link link) {
// TODO: find ui-link assoc. with parameter; create or update.
// TODO: post event
}
void removeLink(Link link) {
// TODO: find ui-link assoc. with parameter; update or remove.
// TODO: post event
}
void addOrUpdateHost(Host host) {
// TODO: find or create host assoc. with parameter
// TODO: post event
}
void moveHost(Host host, Host prevHost) {
// TODO: process host-move
// TODO: post event
}
void removeHost(Host host) {
// TODO: find host assoc. with parameter; remove from model
}
}
......
......@@ -25,6 +25,8 @@ import org.apache.felix.scr.annotations.Service;
import org.onosproject.cluster.ClusterEvent;
import org.onosproject.cluster.ClusterEventListener;
import org.onosproject.cluster.ClusterService;
import org.onosproject.cluster.ControllerNode;
import org.onosproject.cluster.RoleInfo;
import org.onosproject.event.AbstractListenerManager;
import org.onosproject.incubator.net.PortStatisticsService;
import org.onosproject.incubator.net.tunnel.TunnelService;
......@@ -32,6 +34,9 @@ import org.onosproject.mastership.MastershipEvent;
import org.onosproject.mastership.MastershipListener;
import org.onosproject.mastership.MastershipService;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Host;
import org.onosproject.net.Link;
import org.onosproject.net.device.DeviceEvent;
import org.onosproject.net.device.DeviceListener;
import org.onosproject.net.device.DeviceService;
......@@ -47,6 +52,7 @@ import org.onosproject.net.intent.IntentService;
import org.onosproject.net.link.LinkEvent;
import org.onosproject.net.link.LinkListener;
import org.onosproject.net.link.LinkService;
import org.onosproject.net.region.Region;
import org.onosproject.net.region.RegionEvent;
import org.onosproject.net.region.RegionListener;
import org.onosproject.net.region.RegionService;
......@@ -178,28 +184,71 @@ public final class UiSharedTopologyModel
private class InternalClusterListener implements ClusterEventListener {
@Override
public void event(ClusterEvent event) {
// TODO: handle cluster event
ControllerNode cnode = event.subject();
switch (event.type()) {
case INSTANCE_ADDED:
case INSTANCE_ACTIVATED:
case INSTANCE_READY:
case INSTANCE_DEACTIVATED:
cache.addOrUpdateClusterMember(cnode);
break;
case INSTANCE_REMOVED:
cache.removeClusterMember(cnode);
break;
default:
break;
}
}
}
private class InternalMastershipListener implements MastershipListener {
@Override
public void event(MastershipEvent event) {
// TODO: handle mastership event
DeviceId deviceId = event.subject();
RoleInfo roleInfo = event.roleInfo();
switch (event.type()) {
case MASTER_CHANGED:
case BACKUPS_CHANGED:
cache.updateMasterships(deviceId, roleInfo);
break;
default:
break;
}
}
}
private class InternalRegionListener implements RegionListener {
@Override
public void event(RegionEvent event) {
// TODO: handle region event
Region region = event.subject();
switch (event.type()) {
case REGION_ADDED:
case REGION_UPDATED:
case REGION_MEMBERSHIP_CHANGED:
cache.addOrUpdateRegion(region);
break;
case REGION_REMOVED:
cache.removeRegion(region);
break;
default:
break;
}
}
}
private class InternalDeviceListener implements DeviceListener {
@Override
public void event(DeviceEvent event) {
Device device = event.subject();
switch (event.type()) {
......@@ -224,28 +273,71 @@ public final class UiSharedTopologyModel
private class InternalLinkListener implements LinkListener {
@Override
public void event(LinkEvent event) {
// TODO: handle link event
Link link = event.subject();
switch (event.type()) {
case LINK_ADDED:
case LINK_UPDATED:
cache.addOrUpdateLink(link);
break;
case LINK_REMOVED:
cache.removeLink(link);
break;
default:
break;
}
}
}
private class InternalHostListener implements HostListener {
@Override
public void event(HostEvent event) {
// TODO: handle host event
Host host = event.subject();
Host prevHost = event.prevSubject();
switch (event.type()) {
case HOST_ADDED:
case HOST_UPDATED:
cache.addOrUpdateHost(host);
break;
case HOST_MOVED:
cache.moveHost(host, prevHost);
break;
case HOST_REMOVED:
cache.removeHost(host);
break;
default:
break;
}
}
}
// =======================================================================
// NOTE: Neither intents nor flows are modeled by the UiTopology.
// Rather, they are serviced directly from this class.
// Additionally, since we are only retrieving counts (in the current
// implementation), we'll fetch them on demand from the service.
// Thus, the following internal listeners are stubs only (for now).
// =======================================================================
private class InternalIntentListener implements IntentListener {
@Override
public void event(IntentEvent event) {
// TODO: handle intent event
// do nothing (for now)
}
}
private class InternalFlowRuleListener implements FlowRuleListener {
@Override
public void event(FlowRuleEvent event) {
// TODO: handle flowrule event
// do nothing (for now)
}
}
......