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 @@ ...@@ -16,8 +16,12 @@
16 16
17 package org.onosproject.ui.model.topo; 17 package org.onosproject.ui.model.topo;
18 18
19 +import org.onosproject.cluster.NodeId;
20 +
19 import java.util.ArrayList; 21 import java.util.ArrayList;
22 +import java.util.HashMap;
20 import java.util.List; 23 import java.util.List;
24 +import java.util.Map;
21 25
22 /** 26 /**
23 * Encapsulates the notion of the ONOS cluster. 27 * Encapsulates the notion of the ONOS cluster.
...@@ -25,6 +29,12 @@ import java.util.List; ...@@ -25,6 +29,12 @@ import java.util.List;
25 class UiCluster extends UiElement { 29 class UiCluster extends UiElement {
26 30
27 private final List<UiClusterMember> members = new ArrayList<>(); 31 private final List<UiClusterMember> members = new ArrayList<>();
32 + private final Map<NodeId, UiClusterMember> lookup = new HashMap<>();
33 +
34 + @Override
35 + public String toString() {
36 + return String.valueOf(members.size()) + "-member cluster";
37 + }
28 38
29 /** 39 /**
30 * Removes all cluster members. 40 * Removes all cluster members.
...@@ -32,4 +42,34 @@ class UiCluster extends UiElement { ...@@ -32,4 +42,34 @@ class UiCluster extends UiElement {
32 void clear() { 42 void clear() {
33 members.clear(); 43 members.clear();
34 } 44 }
45 +
46 + /**
47 + * Returns the cluster member with the given identifier, or null if no
48 + * such member exists.
49 + *
50 + * @param id identifier of member to find
51 + * @return corresponding member
52 + */
53 + public UiClusterMember find(NodeId id) {
54 + return lookup.get(id);
55 + }
56 +
57 + /**
58 + * Adds the given member to the cluster.
59 + *
60 + * @param member member to add
61 + */
62 + public void add(UiClusterMember member) {
63 + members.add(member);
64 + lookup.put(member.id(), member);
65 + }
66 +
67 + /**
68 + * Returns the number of members in the cluster.
69 + *
70 + * @return number of members
71 + */
72 + public int size() {
73 + return members.size();
74 + }
35 } 75 }
......
...@@ -16,8 +16,41 @@ ...@@ -16,8 +16,41 @@
16 16
17 package org.onosproject.ui.model.topo; 17 package org.onosproject.ui.model.topo;
18 18
19 +import org.onosproject.cluster.ControllerNode;
20 +import org.onosproject.cluster.NodeId;
21 +
19 /** 22 /**
20 * Represents an individual member of the cluster (ONOS instance). 23 * Represents an individual member of the cluster (ONOS instance).
21 */ 24 */
22 public class UiClusterMember extends UiElement { 25 public class UiClusterMember extends UiElement {
26 +
27 + private final ControllerNode cnode;
28 +
29 + /**
30 + * Constructs a cluster member, with a reference to the specified
31 + * controller node instance.
32 + *
33 + * @param cnode underlying controller node.
34 + */
35 + public UiClusterMember(ControllerNode cnode) {
36 + this.cnode = cnode;
37 + }
38 +
39 + /**
40 + * Updates the information about this cluster member.
41 + *
42 + * @param cnode underlying controller node
43 + */
44 + public void update(ControllerNode cnode) {
45 + // TODO: update our information cache appropriately
46 + }
47 +
48 + /**
49 + * Returns the identity of the cluster member.
50 + *
51 + * @return member identifier
52 + */
53 + public NodeId id() {
54 + return cnode.id();
55 + }
23 } 56 }
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
16 16
17 package org.onosproject.ui.model.topo; 17 package org.onosproject.ui.model.topo;
18 18
19 +import org.onosproject.cluster.NodeId;
19 import org.slf4j.Logger; 20 import org.slf4j.Logger;
20 import org.slf4j.LoggerFactory; 21 import org.slf4j.LoggerFactory;
21 22
...@@ -32,6 +33,11 @@ public class UiTopology extends UiElement { ...@@ -32,6 +33,11 @@ public class UiTopology extends UiElement {
32 private final UiCluster uiCluster = new UiCluster(); 33 private final UiCluster uiCluster = new UiCluster();
33 private final Set<UiRegion> uiRegions = new TreeSet<>(); 34 private final Set<UiRegion> uiRegions = new TreeSet<>();
34 35
36 + @Override
37 + public String toString() {
38 + return "Topology: " + uiCluster + ", " + uiRegions.size() + " regions";
39 + }
40 +
35 /** 41 /**
36 * Clears the topology state; that is, drops all regions, devices, hosts, 42 * Clears the topology state; that is, drops all regions, devices, hosts,
37 * links, and cluster members. 43 * links, and cluster members.
...@@ -41,4 +47,42 @@ public class UiTopology extends UiElement { ...@@ -41,4 +47,42 @@ public class UiTopology extends UiElement {
41 uiRegions.clear(); 47 uiRegions.clear();
42 uiCluster.clear(); 48 uiCluster.clear();
43 } 49 }
50 +
51 + /**
52 + * Returns the cluster member with the given identifier, or null if no
53 + * such member.
54 + *
55 + * @param id cluster node identifier
56 + * @return the cluster member with that identifier
57 + */
58 + public UiClusterMember findClusterMember(NodeId id) {
59 + return uiCluster.find(id);
60 + }
61 +
62 + /**
63 + * Adds the given cluster member to the topology model.
64 + *
65 + * @param member cluster member to add
66 + */
67 + public void add(UiClusterMember member) {
68 + uiCluster.add(member);
69 + }
70 +
71 + /**
72 + * Returns the number of members in the cluster.
73 + *
74 + * @return number of cluster members
75 + */
76 + public int clusterMemberCount() {
77 + return uiCluster.size();
78 + }
79 +
80 + /**
81 + * Returns the number of regions configured in the topology.
82 + *
83 + * @return number of regions
84 + */
85 + public int regionCount() {
86 + return uiRegions.size();
87 + }
44 } 88 }
......
...@@ -24,6 +24,7 @@ import org.onosproject.net.DeviceId; ...@@ -24,6 +24,7 @@ import org.onosproject.net.DeviceId;
24 import org.onosproject.net.Host; 24 import org.onosproject.net.Host;
25 import org.onosproject.net.Link; 25 import org.onosproject.net.Link;
26 import org.onosproject.net.region.Region; 26 import org.onosproject.net.region.Region;
27 +import org.onosproject.ui.model.topo.UiClusterMember;
27 import org.onosproject.ui.model.topo.UiDevice; 28 import org.onosproject.ui.model.topo.UiDevice;
28 import org.onosproject.ui.model.topo.UiTopology; 29 import org.onosproject.ui.model.topo.UiTopology;
29 30
...@@ -42,6 +43,11 @@ class ModelCache { ...@@ -42,6 +43,11 @@ class ModelCache {
42 this.dispatcher = eventDispatcher; 43 this.dispatcher = eventDispatcher;
43 } 44 }
44 45
46 + @Override
47 + public String toString() {
48 + return "ModelCache{" + uiTopology + "}";
49 + }
50 +
45 /** 51 /**
46 * Clear our model. 52 * Clear our model.
47 */ 53 */
...@@ -61,27 +67,21 @@ class ModelCache { ...@@ -61,27 +67,21 @@ class ModelCache {
61 } 67 }
62 68
63 69
64 - void addOrUpdateDevice(Device device) { 70 + /**
65 - // TODO: find or create device assoc. with parameter 71 + * Updates the model (adds a new instance if necessary) with the given
66 - // FIXME 72 + * controller node information.
67 - UiDevice uiDevice = new UiDevice(); 73 + *
68 - 74 + * @param cnode controller node to be added/updated
69 - // TODO: post the (correct) event 75 + */
70 - dispatcher.post(new UiModelEvent(DEVICE_ADDED, uiDevice));
71 - }
72 -
73 - void removeDevice(Device device) {
74 - // TODO: get UiDevice associated with the given parameter; remove from model
75 - // FIXME
76 - UiDevice uiDevice = new UiDevice();
77 -
78 - // TODO: post the (correct) event
79 - dispatcher.post(new UiModelEvent(DEVICE_REMOVED, uiDevice));
80 -
81 - }
82 -
83 void addOrUpdateClusterMember(ControllerNode cnode) { 76 void addOrUpdateClusterMember(ControllerNode cnode) {
84 - // TODO: find or create cluster member assoc. with parameter 77 + UiClusterMember member = uiTopology.findClusterMember(cnode.id());
78 + if (member != null) {
79 + member.update(cnode);
80 + } else {
81 + member = new UiClusterMember(cnode);
82 + uiTopology.add(member);
83 + }
84 +
85 // TODO: post event 85 // TODO: post event
86 } 86 }
87 87
...@@ -90,7 +90,6 @@ class ModelCache { ...@@ -90,7 +90,6 @@ class ModelCache {
90 // TODO: post event 90 // TODO: post event
91 } 91 }
92 92
93 -
94 void updateMasterships(DeviceId deviceId, RoleInfo roleInfo) { 93 void updateMasterships(DeviceId deviceId, RoleInfo roleInfo) {
95 // TODO: store the updated mastership information 94 // TODO: store the updated mastership information
96 // TODO: post event 95 // TODO: post event
...@@ -106,6 +105,25 @@ class ModelCache { ...@@ -106,6 +105,25 @@ class ModelCache {
106 // TODO: post event 105 // TODO: post event
107 } 106 }
108 107
108 + void addOrUpdateDevice(Device device) {
109 + // TODO: find or create device assoc. with parameter
110 + // FIXME
111 + UiDevice uiDevice = new UiDevice();
112 +
113 + // TODO: post the (correct) event
114 + dispatcher.post(new UiModelEvent(DEVICE_ADDED, uiDevice));
115 + }
116 +
117 + void removeDevice(Device device) {
118 + // TODO: get UiDevice associated with the given parameter; remove from model
119 + // FIXME
120 + UiDevice uiDevice = new UiDevice();
121 +
122 + // TODO: post the (correct) event
123 + dispatcher.post(new UiModelEvent(DEVICE_REMOVED, uiDevice));
124 +
125 + }
126 +
109 void addOrUpdateLink(Link link) { 127 void addOrUpdateLink(Link link) {
110 // TODO: find ui-link assoc. with parameter; create or update. 128 // TODO: find ui-link assoc. with parameter; create or update.
111 // TODO: post event 129 // TODO: post event
...@@ -129,4 +147,22 @@ class ModelCache { ...@@ -129,4 +147,22 @@ class ModelCache {
129 void removeHost(Host host) { 147 void removeHost(Host host) {
130 // TODO: find host assoc. with parameter; remove from model 148 // TODO: find host assoc. with parameter; remove from model
131 } 149 }
150 +
151 + /**
152 + * Returns the number of members in the cluster.
153 + *
154 + * @return number of cluster members
155 + */
156 + public int clusterMemberCount() {
157 + return uiTopology.clusterMemberCount();
158 + }
159 +
160 + /**
161 + * Returns the number of regions configured in the topology.
162 + *
163 + * @return number of regions
164 + */
165 + public int regionCount() {
166 + return uiTopology.regionCount();
167 + }
132 } 168 }
......
1 +/*
2 + * Copyright 2016-present Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +
17 +package org.onosproject.ui.impl.topo.model;
18 +
19 +/**
20 + * Base class for model test classes.
21 + */
22 +public abstract class AbstractModelTest {
23 +
24 + /**
25 + * System agnostic end-of-line character.
26 + */
27 + protected static final String EOL = String.format("%n");
28 +
29 + /**
30 + * Prints the given string to stdout.
31 + *
32 + * @param s string to print
33 + */
34 + protected void print(String s) {
35 + System.out.println(s);
36 + }
37 +
38 + /**
39 + * Prints the toString() of the given object to stdout.
40 + *
41 + * @param o object to print
42 + */
43 + protected void print(Object o) {
44 + print(o.toString());
45 + }
46 +
47 + /**
48 + * Prints the formatted string to stdout.
49 + *
50 + * @param fmt format string
51 + * @param params parameters
52 + * @see String#format(String, Object...)
53 + */
54 + protected void print(String fmt, Object... params) {
55 + print(String.format(fmt, params));
56 + }
57 +
58 +}
1 +/*
2 + * Copyright 2016-present Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +
17 +package org.onosproject.ui.impl.topo.model;
18 +
19 +import org.junit.Test;
20 +import org.onosproject.event.EventDispatcher;
21 +
22 +import static org.junit.Assert.assertEquals;
23 +
24 +/**
25 + * Unit tests for {@link ModelCache}.
26 + */
27 +public class ModelCacheTest extends AbstractModelTest {
28 +
29 + private static final EventDispatcher DISPATCHER = event -> {
30 + // Do we care?
31 + };
32 +
33 + private ModelCache cache;
34 +
35 + @Test
36 + public void basic() {
37 + cache = new ModelCache(DISPATCHER);
38 + print(cache);
39 + assertEquals("unex # members", 0, cache.clusterMemberCount());
40 + assertEquals("unex # regions", 0, cache.regionCount());
41 + }
42 +
43 +}