Committed by
Gerrit Code Review
ONOS-3347 - HostMoved event now processed correctly.
- added new DefaultHashMap utility class - updated TopoViewMsgHdlrBase for cleaner event translation. Change-Id: I1c5e8c981e2d617366c25f497dc9336e09684a2e
Showing
5 changed files
with
192 additions
and
19 deletions
1 | +/* | ||
2 | + * Copyright 2015 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.onlab.util; | ||
18 | + | ||
19 | +import java.util.HashMap; | ||
20 | + | ||
21 | +/** | ||
22 | + * HashMap that returns a default value for unmapped keys. | ||
23 | + */ | ||
24 | +public class DefaultHashMap<K, V> extends HashMap<K, V> { | ||
25 | + | ||
26 | + /** Default value to return when no key binding exists. */ | ||
27 | + protected V defaultValue; | ||
28 | + | ||
29 | + /** | ||
30 | + * Constructs an empty map with the given default value. | ||
31 | + * | ||
32 | + * @param defaultValue the default value | ||
33 | + */ | ||
34 | + public DefaultHashMap(V defaultValue) { | ||
35 | + this.defaultValue = defaultValue; | ||
36 | + } | ||
37 | + | ||
38 | + @Override | ||
39 | + public V get(Object k) { | ||
40 | + return containsKey(k) ? super.get(k) : defaultValue; | ||
41 | + } | ||
42 | +} | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
1 | +/* | ||
2 | + * Copyright 2015 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.onlab.util; | ||
18 | + | ||
19 | +import org.junit.Test; | ||
20 | + | ||
21 | +import static org.junit.Assert.assertEquals; | ||
22 | + | ||
23 | +/** | ||
24 | + * Unit tests for {@link DefaultHashMap}. | ||
25 | + */ | ||
26 | +public class DefaultHashMapTest { | ||
27 | + | ||
28 | + private static final String ONE = "one"; | ||
29 | + private static final String TWO = "two"; | ||
30 | + private static final String THREE = "three"; | ||
31 | + private static final String FOUR = "four"; | ||
32 | + | ||
33 | + private static final String ALPHA = "Alpha"; | ||
34 | + private static final String BETA = "Beta"; | ||
35 | + private static final String OMEGA = "Omega"; | ||
36 | + | ||
37 | + private DefaultHashMap<String, Integer> map; | ||
38 | + private DefaultHashMap<String, String> chartis; | ||
39 | + | ||
40 | + private void loadMap() { | ||
41 | + map.put(ONE, 1); | ||
42 | + map.put(TWO, 2); | ||
43 | + } | ||
44 | + | ||
45 | + private void fortioCharti() { | ||
46 | + chartis.put(ONE, ALPHA); | ||
47 | + chartis.put(TWO, BETA); | ||
48 | + } | ||
49 | + | ||
50 | + @Test | ||
51 | + public void nullDefaultIsAllowed() { | ||
52 | + // but makes this class behave no different than HashMap | ||
53 | + map = new DefaultHashMap<>(null); | ||
54 | + loadMap(); | ||
55 | + assertEquals("missing 1", 1, (int) map.get(ONE)); | ||
56 | + assertEquals("missing 2", 2, (int) map.get(TWO)); | ||
57 | + assertEquals("three?", null, map.get(THREE)); | ||
58 | + assertEquals("four?", null, map.get(FOUR)); | ||
59 | + } | ||
60 | + | ||
61 | + @Test | ||
62 | + public void defaultToFive() { | ||
63 | + map = new DefaultHashMap<>(5); | ||
64 | + loadMap(); | ||
65 | + assertEquals("missing 1", 1, (int) map.get(ONE)); | ||
66 | + assertEquals("missing 2", 2, (int) map.get(TWO)); | ||
67 | + assertEquals("three?", 5, (int) map.get(THREE)); | ||
68 | + assertEquals("four?", 5, (int) map.get(FOUR)); | ||
69 | + } | ||
70 | + | ||
71 | + @Test | ||
72 | + public void defaultToOmega() { | ||
73 | + chartis = new DefaultHashMap<>(OMEGA); | ||
74 | + fortioCharti(); | ||
75 | + assertEquals("missing 1", ALPHA, chartis.get(ONE)); | ||
76 | + assertEquals("missing 2", BETA, chartis.get(TWO)); | ||
77 | + assertEquals("three?", OMEGA, chartis.get(THREE)); | ||
78 | + assertEquals("four?", OMEGA, chartis.get(FOUR)); | ||
79 | + } | ||
80 | + | ||
81 | +} |
... | @@ -20,6 +20,7 @@ import com.fasterxml.jackson.databind.node.ArrayNode; | ... | @@ -20,6 +20,7 @@ import com.fasterxml.jackson.databind.node.ArrayNode; |
20 | import com.fasterxml.jackson.databind.node.ObjectNode; | 20 | import com.fasterxml.jackson.databind.node.ObjectNode; |
21 | import org.onlab.osgi.ServiceDirectory; | 21 | import org.onlab.osgi.ServiceDirectory; |
22 | import org.onlab.packet.IpAddress; | 22 | import org.onlab.packet.IpAddress; |
23 | +import org.onlab.util.DefaultHashMap; | ||
23 | import org.onosproject.cluster.ClusterEvent; | 24 | import org.onosproject.cluster.ClusterEvent; |
24 | import org.onosproject.cluster.ClusterService; | 25 | import org.onosproject.cluster.ClusterService; |
25 | import org.onosproject.cluster.ControllerNode; | 26 | import org.onosproject.cluster.ControllerNode; |
... | @@ -80,17 +81,9 @@ import java.util.concurrent.ConcurrentHashMap; | ... | @@ -80,17 +81,9 @@ import java.util.concurrent.ConcurrentHashMap; |
80 | 81 | ||
81 | import static com.google.common.base.Preconditions.checkNotNull; | 82 | import static com.google.common.base.Preconditions.checkNotNull; |
82 | import static com.google.common.base.Strings.isNullOrEmpty; | 83 | import static com.google.common.base.Strings.isNullOrEmpty; |
83 | -import static org.onosproject.cluster.ClusterEvent.Type.INSTANCE_ADDED; | ||
84 | -import static org.onosproject.cluster.ClusterEvent.Type.INSTANCE_REMOVED; | ||
85 | import static org.onosproject.cluster.ControllerNode.State.ACTIVE; | 84 | import static org.onosproject.cluster.ControllerNode.State.ACTIVE; |
86 | import static org.onosproject.net.DefaultEdgeLink.createEdgeLink; | 85 | import static org.onosproject.net.DefaultEdgeLink.createEdgeLink; |
87 | import static org.onosproject.net.PortNumber.portNumber; | 86 | import static org.onosproject.net.PortNumber.portNumber; |
88 | -import static org.onosproject.net.device.DeviceEvent.Type.DEVICE_ADDED; | ||
89 | -import static org.onosproject.net.device.DeviceEvent.Type.DEVICE_REMOVED; | ||
90 | -import static org.onosproject.net.host.HostEvent.Type.HOST_ADDED; | ||
91 | -import static org.onosproject.net.host.HostEvent.Type.HOST_REMOVED; | ||
92 | -import static org.onosproject.net.link.LinkEvent.Type.LINK_ADDED; | ||
93 | -import static org.onosproject.net.link.LinkEvent.Type.LINK_REMOVED; | ||
94 | import static org.onosproject.ui.topo.TopoConstants.CoreButtons; | 87 | import static org.onosproject.ui.topo.TopoConstants.CoreButtons; |
95 | import static org.onosproject.ui.topo.TopoConstants.Properties; | 88 | import static org.onosproject.ui.topo.TopoConstants.Properties; |
96 | import static org.onosproject.ui.topo.TopoUtils.compactLinkString; | 89 | import static org.onosproject.ui.topo.TopoUtils.compactLinkString; |
... | @@ -100,6 +93,33 @@ import static org.onosproject.ui.topo.TopoUtils.compactLinkString; | ... | @@ -100,6 +93,33 @@ import static org.onosproject.ui.topo.TopoUtils.compactLinkString; |
100 | */ | 93 | */ |
101 | public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler { | 94 | public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler { |
102 | 95 | ||
96 | + // default to an "add" event... | ||
97 | + private static final DefaultHashMap<ClusterEvent.Type, String> CLUSTER_EVENT = | ||
98 | + new DefaultHashMap<>("addInstance"); | ||
99 | + | ||
100 | + // default to an "update" event... | ||
101 | + private static final DefaultHashMap<DeviceEvent.Type, String> DEVICE_EVENT = | ||
102 | + new DefaultHashMap<>("updateDevice"); | ||
103 | + private static final DefaultHashMap<LinkEvent.Type, String> LINK_EVENT = | ||
104 | + new DefaultHashMap<>("updateLink"); | ||
105 | + private static final DefaultHashMap<HostEvent.Type, String> HOST_EVENT = | ||
106 | + new DefaultHashMap<>("updateHost"); | ||
107 | + | ||
108 | + // but call out specific events that we care to differentiate... | ||
109 | + static { | ||
110 | + CLUSTER_EVENT.put(ClusterEvent.Type.INSTANCE_REMOVED, "removeInstance"); | ||
111 | + | ||
112 | + DEVICE_EVENT.put(DeviceEvent.Type.DEVICE_ADDED, "addDevice"); | ||
113 | + DEVICE_EVENT.put(DeviceEvent.Type.DEVICE_REMOVED, "removeDevice"); | ||
114 | + | ||
115 | + LINK_EVENT.put(LinkEvent.Type.LINK_ADDED, "addLink"); | ||
116 | + LINK_EVENT.put(LinkEvent.Type.LINK_REMOVED, "removeLink"); | ||
117 | + | ||
118 | + HOST_EVENT.put(HostEvent.Type.HOST_ADDED, "addHost"); | ||
119 | + HOST_EVENT.put(HostEvent.Type.HOST_REMOVED, "removeHost"); | ||
120 | + HOST_EVENT.put(HostEvent.Type.HOST_MOVED, "moveHost"); | ||
121 | + } | ||
122 | + | ||
103 | protected static final Logger log = | 123 | protected static final Logger log = |
104 | LoggerFactory.getLogger(TopologyViewMessageHandlerBase.class); | 124 | LoggerFactory.getLogger(TopologyViewMessageHandlerBase.class); |
105 | 125 | ||
... | @@ -204,7 +224,7 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler { | ... | @@ -204,7 +224,7 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler { |
204 | } | 224 | } |
205 | 225 | ||
206 | // Produces a cluster instance message to the client. | 226 | // Produces a cluster instance message to the client. |
207 | - protected ObjectNode instanceMessage(ClusterEvent event, String messageType) { | 227 | + protected ObjectNode instanceMessage(ClusterEvent event, String msgType) { |
208 | ControllerNode node = event.subject(); | 228 | ControllerNode node = event.subject(); |
209 | int switchCount = mastershipService.getDevicesOf(node.id()).size(); | 229 | int switchCount = mastershipService.getDevicesOf(node.id()).size(); |
210 | ObjectNode payload = objectNode() | 230 | ObjectNode payload = objectNode() |
... | @@ -222,10 +242,7 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler { | ... | @@ -222,10 +242,7 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler { |
222 | payload.set("labels", labels); | 242 | payload.set("labels", labels); |
223 | addMetaUi(node.id().toString(), payload); | 243 | addMetaUi(node.id().toString(), payload); |
224 | 244 | ||
225 | - String type = messageType != null ? messageType : | 245 | + String type = msgType != null ? msgType : CLUSTER_EVENT.get(event.type()); |
226 | - ((event.type() == INSTANCE_ADDED) ? "addInstance" : | ||
227 | - ((event.type() == INSTANCE_REMOVED ? "removeInstance" : | ||
228 | - "addInstance"))); | ||
229 | return JsonUtils.envelope(type, 0, payload); | 246 | return JsonUtils.envelope(type, 0, payload); |
230 | } | 247 | } |
231 | 248 | ||
... | @@ -251,8 +268,7 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler { | ... | @@ -251,8 +268,7 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler { |
251 | addGeoLocation(device, payload); | 268 | addGeoLocation(device, payload); |
252 | addMetaUi(device.id().toString(), payload); | 269 | addMetaUi(device.id().toString(), payload); |
253 | 270 | ||
254 | - String type = (event.type() == DEVICE_ADDED) ? "addDevice" : | 271 | + String type = DEVICE_EVENT.get(event.type()); |
255 | - ((event.type() == DEVICE_REMOVED) ? "removeDevice" : "updateDevice"); | ||
256 | return JsonUtils.envelope(type, 0, payload); | 272 | return JsonUtils.envelope(type, 0, payload); |
257 | } | 273 | } |
258 | 274 | ||
... | @@ -268,8 +284,7 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler { | ... | @@ -268,8 +284,7 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler { |
268 | .put("srcPort", link.src().port().toString()) | 284 | .put("srcPort", link.src().port().toString()) |
269 | .put("dst", link.dst().deviceId().toString()) | 285 | .put("dst", link.dst().deviceId().toString()) |
270 | .put("dstPort", link.dst().port().toString()); | 286 | .put("dstPort", link.dst().port().toString()); |
271 | - String type = (event.type() == LINK_ADDED) ? "addLink" : | 287 | + String type = LINK_EVENT.get(event.type()); |
272 | - ((event.type() == LINK_REMOVED) ? "removeLink" : "updateLink"); | ||
273 | return JsonUtils.envelope(type, 0, payload); | 288 | return JsonUtils.envelope(type, 0, payload); |
274 | } | 289 | } |
275 | 290 | ||
... | @@ -277,20 +292,24 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler { | ... | @@ -277,20 +292,24 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler { |
277 | protected ObjectNode hostMessage(HostEvent event) { | 292 | protected ObjectNode hostMessage(HostEvent event) { |
278 | Host host = event.subject(); | 293 | Host host = event.subject(); |
279 | String hostType = host.annotations().value(AnnotationKeys.TYPE); | 294 | String hostType = host.annotations().value(AnnotationKeys.TYPE); |
295 | + HostLocation prevLoc = event.prevLocation(); | ||
296 | + | ||
280 | ObjectNode payload = objectNode() | 297 | ObjectNode payload = objectNode() |
281 | .put("id", host.id().toString()) | 298 | .put("id", host.id().toString()) |
282 | .put("type", isNullOrEmpty(hostType) ? "endstation" : hostType) | 299 | .put("type", isNullOrEmpty(hostType) ? "endstation" : hostType) |
283 | .put("ingress", compactLinkString(edgeLink(host, true))) | 300 | .put("ingress", compactLinkString(edgeLink(host, true))) |
284 | .put("egress", compactLinkString(edgeLink(host, false))); | 301 | .put("egress", compactLinkString(edgeLink(host, false))); |
285 | payload.set("cp", hostConnect(host.location())); | 302 | payload.set("cp", hostConnect(host.location())); |
303 | + if (prevLoc != null) { | ||
304 | + payload.set("prevCp", hostConnect(event.prevLocation())); | ||
305 | + } | ||
286 | payload.set("labels", labels(ip(host.ipAddresses()), | 306 | payload.set("labels", labels(ip(host.ipAddresses()), |
287 | host.mac().toString())); | 307 | host.mac().toString())); |
288 | payload.set("props", props(host.annotations())); | 308 | payload.set("props", props(host.annotations())); |
289 | addGeoLocation(host, payload); | 309 | addGeoLocation(host, payload); |
290 | addMetaUi(host.id().toString(), payload); | 310 | addMetaUi(host.id().toString(), payload); |
291 | 311 | ||
292 | - String type = (event.type() == HOST_ADDED) ? "addHost" : | 312 | + String type = HOST_EVENT.get(event.type()); |
293 | - ((event.type() == HOST_REMOVED) ? "removeHost" : "updateHost"); | ||
294 | return JsonUtils.envelope(type, 0, payload); | 313 | return JsonUtils.envelope(type, 0, payload); |
295 | } | 314 | } |
296 | 315 | ... | ... |
... | @@ -55,6 +55,7 @@ | ... | @@ -55,6 +55,7 @@ |
55 | removeDevice: tfs, | 55 | removeDevice: tfs, |
56 | addHost: tfs, | 56 | addHost: tfs, |
57 | updateHost: tfs, | 57 | updateHost: tfs, |
58 | + moveHost: tfs, | ||
58 | removeHost: tfs, | 59 | removeHost: tfs, |
59 | addLink: tfs, | 60 | addLink: tfs, |
60 | updateLink: tfs, | 61 | updateLink: tfs, | ... | ... |
... | @@ -187,6 +187,35 @@ | ... | @@ -187,6 +187,35 @@ |
187 | } | 187 | } |
188 | } | 188 | } |
189 | 189 | ||
190 | + function moveHost(data) { | ||
191 | + var id = data.id, | ||
192 | + d = lu[id], | ||
193 | + lnk; | ||
194 | + if (d) { | ||
195 | + // first remove the old host link | ||
196 | + removeLinkElement(d.linkData); | ||
197 | + | ||
198 | + // merge new data | ||
199 | + angular.extend(d, data); | ||
200 | + if (tms.positionNode(d, true)) { | ||
201 | + sendUpdateMeta(d); | ||
202 | + } | ||
203 | + | ||
204 | + // now create a new host link | ||
205 | + lnk = tms.createHostLink(data); | ||
206 | + if (lnk) { | ||
207 | + d.linkData = lnk; | ||
208 | + network.links.push(lnk); | ||
209 | + lu[d.ingress] = lnk; | ||
210 | + lu[d.egress] = lnk; | ||
211 | + } | ||
212 | + | ||
213 | + updateNodes(); | ||
214 | + updateLinks(); | ||
215 | + fResume(); | ||
216 | + } | ||
217 | + } | ||
218 | + | ||
190 | function removeHost(data) { | 219 | function removeHost(data) { |
191 | var id = data.id, | 220 | var id = data.id, |
192 | d = lu[id]; | 221 | d = lu[id]; |
... | @@ -1142,6 +1171,7 @@ | ... | @@ -1142,6 +1171,7 @@ |
1142 | removeDevice: removeDevice, | 1171 | removeDevice: removeDevice, |
1143 | addHost: addHost, | 1172 | addHost: addHost, |
1144 | updateHost: updateHost, | 1173 | updateHost: updateHost, |
1174 | + moveHost: moveHost, | ||
1145 | removeHost: removeHost, | 1175 | removeHost: removeHost, |
1146 | addLink: addLink, | 1176 | addLink: addLink, |
1147 | updateLink: updateLink, | 1177 | updateLink: updateLink, | ... | ... |
-
Please register or login to post a comment