Thomas Vachuska
Committed by Gerrit Code Review

ONOS-4137 Adding a "ready" check-mark glyph to the node instances.

Introduced a new INSTANCE_READY type of ClusterEvent.

Change-Id: I7f77ebae56cb18c196cd3ec7f2735faa4ca363db
...@@ -42,6 +42,11 @@ public class ClusterEvent extends AbstractEvent<ClusterEvent.Type, ControllerNod ...@@ -42,6 +42,11 @@ public class ClusterEvent extends AbstractEvent<ClusterEvent.Type, ControllerNod
42 INSTANCE_ACTIVATED, 42 INSTANCE_ACTIVATED,
43 43
44 /** 44 /**
45 + * Signifies that a cluster instance became ready.
46 + */
47 + INSTANCE_READY,
48 +
49 + /**
45 * Signifies that a cluster instance became inactive. 50 * Signifies that a cluster instance became inactive.
46 */ 51 */
47 INSTANCE_DEACTIVATED 52 INSTANCE_DEACTIVATED
......
...@@ -43,6 +43,7 @@ import org.onosproject.store.serializers.KryoSerializer; ...@@ -43,6 +43,7 @@ import org.onosproject.store.serializers.KryoSerializer;
43 import org.slf4j.Logger; 43 import org.slf4j.Logger;
44 44
45 import java.util.Map; 45 import java.util.Map;
46 +import java.util.Objects;
46 import java.util.Set; 47 import java.util.Set;
47 import java.util.concurrent.ExecutorService; 48 import java.util.concurrent.ExecutorService;
48 import java.util.concurrent.Executors; 49 import java.util.concurrent.Executors;
...@@ -53,6 +54,9 @@ import java.util.stream.Collectors; ...@@ -53,6 +54,9 @@ import java.util.stream.Collectors;
53 54
54 import static com.google.common.base.Preconditions.checkNotNull; 55 import static com.google.common.base.Preconditions.checkNotNull;
55 import static org.onlab.util.Tools.groupedThreads; 56 import static org.onlab.util.Tools.groupedThreads;
57 +import static org.onosproject.cluster.ClusterEvent.Type.INSTANCE_ACTIVATED;
58 +import static org.onosproject.cluster.ClusterEvent.Type.INSTANCE_DEACTIVATED;
59 +import static org.onosproject.cluster.ClusterEvent.Type.INSTANCE_READY;
56 import static org.slf4j.LoggerFactory.getLogger; 60 import static org.slf4j.LoggerFactory.getLogger;
57 61
58 @Component(immediate = true) 62 @Component(immediate = true)
...@@ -196,8 +200,12 @@ public class DistributedClusterStore ...@@ -196,8 +200,12 @@ public class DistributedClusterStore
196 } 200 }
197 201
198 private void updateState(NodeId nodeId, State newState) { 202 private void updateState(NodeId nodeId, State newState) {
203 + State currentState = nodeStates.get(nodeId);
204 + if (!Objects.equals(currentState, newState)) {
199 nodeStates.put(nodeId, newState); 205 nodeStates.put(nodeId, newState);
200 nodeStateLastUpdatedTimes.put(nodeId, DateTime.now()); 206 nodeStateLastUpdatedTimes.put(nodeId, DateTime.now());
207 + notifyStateChange(nodeId, currentState, newState);
208 + }
201 } 209 }
202 210
203 private void heartbeat() { 211 private void heartbeat() {
...@@ -215,12 +223,10 @@ public class DistributedClusterStore ...@@ -215,12 +223,10 @@ public class DistributedClusterStore
215 if (phi >= PHI_FAILURE_THRESHOLD) { 223 if (phi >= PHI_FAILURE_THRESHOLD) {
216 if (currentState.isActive()) { 224 if (currentState.isActive()) {
217 updateState(node.id(), State.INACTIVE); 225 updateState(node.id(), State.INACTIVE);
218 - notifyStateChange(node.id(), State.ACTIVE, State.INACTIVE);
219 } 226 }
220 } else { 227 } else {
221 if (currentState == State.INACTIVE) { 228 if (currentState == State.INACTIVE) {
222 updateState(node.id(), State.ACTIVE); 229 updateState(node.id(), State.ACTIVE);
223 - notifyStateChange(node.id(), State.INACTIVE, State.ACTIVE);
224 } 230 }
225 } 231 }
226 }); 232 });
...@@ -230,11 +236,12 @@ public class DistributedClusterStore ...@@ -230,11 +236,12 @@ public class DistributedClusterStore
230 } 236 }
231 237
232 private void notifyStateChange(NodeId nodeId, State oldState, State newState) { 238 private void notifyStateChange(NodeId nodeId, State oldState, State newState) {
239 + if (oldState != newState) {
233 ControllerNode node = allNodes.get(nodeId); 240 ControllerNode node = allNodes.get(nodeId);
234 - if (newState.isActive()) { 241 + ClusterEvent.Type type = newState == State.READY ? INSTANCE_READY :
235 - notifyDelegate(new ClusterEvent(ClusterEvent.Type.INSTANCE_ACTIVATED, node)); 242 + newState == State.ACTIVE ? INSTANCE_ACTIVATED :
236 - } else { 243 + INSTANCE_DEACTIVATED;
237 - notifyDelegate(new ClusterEvent(ClusterEvent.Type.INSTANCE_DEACTIVATED, node)); 244 + notifyDelegate(new ClusterEvent(type, node));
238 } 245 }
239 } 246 }
240 247
......
...@@ -230,6 +230,7 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler { ...@@ -230,6 +230,7 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler {
230 .put("id", node.id().toString()) 230 .put("id", node.id().toString())
231 .put("ip", node.ip().toString()) 231 .put("ip", node.ip().toString())
232 .put("online", clusterService.getState(node.id()).isActive()) 232 .put("online", clusterService.getState(node.id()).isActive())
233 + .put("ready", clusterService.getState(node.id()).isReady())
233 .put("uiAttached", node.equals(clusterService.getLocalNode())) 234 .put("uiAttached", node.equals(clusterService.getLocalNode()))
234 .put("switches", switchCount); 235 .put("switches", switchCount);
235 236
......
...@@ -767,3 +767,7 @@ html[data-platform='iPad'] #topo-p-detail { ...@@ -767,3 +767,7 @@ html[data-platform='iPad'] #topo-p-detail {
767 fill: #447; 767 fill: #447;
768 } 768 }
769 769
770 +.notReady .readyBadge {
771 + visibility: hidden;
772 +}
773 +
......
...@@ -155,10 +155,15 @@ ...@@ -155,10 +155,15 @@
155 } 155 }
156 156
157 function attachUiBadge(svg) { 157 function attachUiBadge(svg) {
158 - gs.addGlyph(svg, 'uiAttached', 30, true, [12, instCfg.uiDy]) 158 + gs.addGlyph(svg, 'uiAttached', 24, true, [28, instCfg.uiDy])
159 .classed('badgeIcon uiBadge', true); 159 .classed('badgeIcon uiBadge', true);
160 } 160 }
161 161
162 + function attachReadyBadge(svg) {
163 + gs.addGlyph(svg, 'checkMark', 16, true, [12, instCfg.uiDy + 4])
164 + .classed('badgeIcon readyBadge', true);
165 + }
166 +
162 function instColor(id, online) { 167 function instColor(id, online) {
163 return sus.cat7().getColor(id, !online, ts.theme()); 168 return sus.cat7().getColor(id, !online, ts.theme());
164 } 169 }
...@@ -183,6 +188,7 @@ ...@@ -183,6 +188,7 @@
183 188
184 // update online state 189 // update online state
185 el.classed('online', d.online); 190 el.classed('online', d.online);
191 + el.classed('notReady', !d.ready);
186 192
187 // update ui-attached state 193 // update ui-attached state
188 svg.select('use.uiBadge').remove(); 194 svg.select('use.uiBadge').remove();
...@@ -190,6 +196,8 @@ ...@@ -190,6 +196,8 @@
190 attachUiBadge(svg); 196 attachUiBadge(svg);
191 } 197 }
192 198
199 + attachReadyBadge(svg, d.ready);
200 +
193 function updAttr(id, value) { 201 function updAttr(id, value) {
194 svg.select('text.instLabel.'+id).text(value); 202 svg.select('text.instLabel.'+id).text(value);
195 } 203 }
...@@ -204,6 +212,7 @@ ...@@ -204,6 +212,7 @@
204 .append('div') 212 .append('div')
205 .attr('class', 'onosInst') 213 .attr('class', 'onosInst')
206 .classed('online', function (d) { return d.online; }) 214 .classed('online', function (d) { return d.online; })
215 + .classed('notReady', function (d) { return !d.ready; })
207 .on('click', clickInst); 216 .on('click', clickInst);
208 217
209 entering.each(function (d) { 218 entering.each(function (d) {
...@@ -228,6 +237,8 @@ ...@@ -228,6 +237,8 @@
228 attachUiBadge(svg); 237 attachUiBadge(svg);
229 } 238 }
230 239
240 + attachReadyBadge(svg);
241 +
231 var left = c.nodeOx + c.nodeDim, 242 var left = c.nodeOx + c.nodeDim,
232 len = rectAttr.width - left, 243 len = rectAttr.width - left,
233 hlen = len / 2, 244 hlen = len / 2,
......