Simon Hunt

Starting implementation of UI topo modeling. WIP.

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

Change-Id: Iab75f213ca0a7d36619f9c498387b402ac9477af
......@@ -16,8 +16,12 @@
package org.onosproject.ui.model.topo;
import org.onosproject.cluster.NodeId;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Encapsulates the notion of the ONOS cluster.
......@@ -25,6 +29,12 @@ import java.util.List;
class UiCluster extends UiElement {
private final List<UiClusterMember> members = new ArrayList<>();
private final Map<NodeId, UiClusterMember> lookup = new HashMap<>();
@Override
public String toString() {
return String.valueOf(members.size()) + "-member cluster";
}
/**
* Removes all cluster members.
......@@ -32,4 +42,34 @@ class UiCluster extends UiElement {
void clear() {
members.clear();
}
/**
* Returns the cluster member with the given identifier, or null if no
* such member exists.
*
* @param id identifier of member to find
* @return corresponding member
*/
public UiClusterMember find(NodeId id) {
return lookup.get(id);
}
/**
* Adds the given member to the cluster.
*
* @param member member to add
*/
public void add(UiClusterMember member) {
members.add(member);
lookup.put(member.id(), member);
}
/**
* Returns the number of members in the cluster.
*
* @return number of members
*/
public int size() {
return members.size();
}
}
......
......@@ -16,8 +16,41 @@
package org.onosproject.ui.model.topo;
import org.onosproject.cluster.ControllerNode;
import org.onosproject.cluster.NodeId;
/**
* Represents an individual member of the cluster (ONOS instance).
*/
public class UiClusterMember extends UiElement {
private final ControllerNode cnode;
/**
* Constructs a cluster member, with a reference to the specified
* controller node instance.
*
* @param cnode underlying controller node.
*/
public UiClusterMember(ControllerNode cnode) {
this.cnode = cnode;
}
/**
* Updates the information about this cluster member.
*
* @param cnode underlying controller node
*/
public void update(ControllerNode cnode) {
// TODO: update our information cache appropriately
}
/**
* Returns the identity of the cluster member.
*
* @return member identifier
*/
public NodeId id() {
return cnode.id();
}
}
......
......@@ -16,6 +16,7 @@
package org.onosproject.ui.model.topo;
import org.onosproject.cluster.NodeId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -32,6 +33,11 @@ public class UiTopology extends UiElement {
private final UiCluster uiCluster = new UiCluster();
private final Set<UiRegion> uiRegions = new TreeSet<>();
@Override
public String toString() {
return "Topology: " + uiCluster + ", " + uiRegions.size() + " regions";
}
/**
* Clears the topology state; that is, drops all regions, devices, hosts,
* links, and cluster members.
......@@ -41,4 +47,42 @@ public class UiTopology extends UiElement {
uiRegions.clear();
uiCluster.clear();
}
/**
* Returns the cluster member with the given identifier, or null if no
* such member.
*
* @param id cluster node identifier
* @return the cluster member with that identifier
*/
public UiClusterMember findClusterMember(NodeId id) {
return uiCluster.find(id);
}
/**
* Adds the given cluster member to the topology model.
*
* @param member cluster member to add
*/
public void add(UiClusterMember member) {
uiCluster.add(member);
}
/**
* Returns the number of members in the cluster.
*
* @return number of cluster members
*/
public int clusterMemberCount() {
return uiCluster.size();
}
/**
* Returns the number of regions configured in the topology.
*
* @return number of regions
*/
public int regionCount() {
return uiRegions.size();
}
}
......
......@@ -24,6 +24,7 @@ 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.UiClusterMember;
import org.onosproject.ui.model.topo.UiDevice;
import org.onosproject.ui.model.topo.UiTopology;
......@@ -42,6 +43,11 @@ class ModelCache {
this.dispatcher = eventDispatcher;
}
@Override
public String toString() {
return "ModelCache{" + uiTopology + "}";
}
/**
* Clear our model.
*/
......@@ -61,27 +67,21 @@ class ModelCache {
}
void addOrUpdateDevice(Device device) {
// TODO: find or create device assoc. with parameter
// FIXME
UiDevice uiDevice = new 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();
// TODO: post the (correct) event
dispatcher.post(new UiModelEvent(DEVICE_REMOVED, uiDevice));
}
/**
* Updates the model (adds a new instance if necessary) with the given
* controller node information.
*
* @param cnode controller node to be added/updated
*/
void addOrUpdateClusterMember(ControllerNode cnode) {
// TODO: find or create cluster member assoc. with parameter
UiClusterMember member = uiTopology.findClusterMember(cnode.id());
if (member != null) {
member.update(cnode);
} else {
member = new UiClusterMember(cnode);
uiTopology.add(member);
}
// TODO: post event
}
......@@ -90,7 +90,6 @@ class ModelCache {
// TODO: post event
}
void updateMasterships(DeviceId deviceId, RoleInfo roleInfo) {
// TODO: store the updated mastership information
// TODO: post event
......@@ -106,6 +105,25 @@ class ModelCache {
// TODO: post event
}
void addOrUpdateDevice(Device device) {
// TODO: find or create device assoc. with parameter
// FIXME
UiDevice uiDevice = new 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();
// TODO: post the (correct) event
dispatcher.post(new UiModelEvent(DEVICE_REMOVED, uiDevice));
}
void addOrUpdateLink(Link link) {
// TODO: find ui-link assoc. with parameter; create or update.
// TODO: post event
......@@ -129,4 +147,22 @@ class ModelCache {
void removeHost(Host host) {
// TODO: find host assoc. with parameter; remove from model
}
/**
* Returns the number of members in the cluster.
*
* @return number of cluster members
*/
public int clusterMemberCount() {
return uiTopology.clusterMemberCount();
}
/**
* Returns the number of regions configured in the topology.
*
* @return number of regions
*/
public int regionCount() {
return uiTopology.regionCount();
}
}
......
/*
* Copyright 2016-present Open Networking Laboratory
*
* 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 org.onosproject.ui.impl.topo.model;
/**
* Base class for model test classes.
*/
public abstract class AbstractModelTest {
/**
* System agnostic end-of-line character.
*/
protected static final String EOL = String.format("%n");
/**
* Prints the given string to stdout.
*
* @param s string to print
*/
protected void print(String s) {
System.out.println(s);
}
/**
* Prints the toString() of the given object to stdout.
*
* @param o object to print
*/
protected void print(Object o) {
print(o.toString());
}
/**
* Prints the formatted string to stdout.
*
* @param fmt format string
* @param params parameters
* @see String#format(String, Object...)
*/
protected void print(String fmt, Object... params) {
print(String.format(fmt, params));
}
}
/*
* Copyright 2016-present Open Networking Laboratory
*
* 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 org.onosproject.ui.impl.topo.model;
import org.junit.Test;
import org.onosproject.event.EventDispatcher;
import static org.junit.Assert.assertEquals;
/**
* Unit tests for {@link ModelCache}.
*/
public class ModelCacheTest extends AbstractModelTest {
private static final EventDispatcher DISPATCHER = event -> {
// Do we care?
};
private ModelCache cache;
@Test
public void basic() {
cache = new ModelCache(DISPATCHER);
print(cache);
assertEquals("unex # members", 0, cache.clusterMemberCount());
assertEquals("unex # regions", 0, cache.regionCount());
}
}