Adding code to enable GUI failover.
Change-Id: I8423f17349411d24332db8670840438d0d8ec8ba
Showing
7 changed files
with
75 additions
and
99 deletions
| ... | @@ -29,4 +29,13 @@ public interface UiConnection { | ... | @@ -29,4 +29,13 @@ public interface UiConnection { |
| 29 | */ | 29 | */ |
| 30 | void sendMessage(ObjectNode message); | 30 | void sendMessage(ObjectNode message); |
| 31 | 31 | ||
| 32 | + /** | ||
| 33 | + * Composes a message into JSON and sends it to the user interface client. | ||
| 34 | + * | ||
| 35 | + * @param type message type | ||
| 36 | + * @param sid message sequence number | ||
| 37 | + * @param payload message payload | ||
| 38 | + */ | ||
| 39 | + void sendMessage(String type, long sid, ObjectNode payload); | ||
| 40 | + | ||
| 32 | } | 41 | } |
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
tools/test/cells/beastMod
0 → 100644
| 1 | +# Bare metal cluster with rearranged nodes | ||
| 2 | + | ||
| 3 | +# Use the 10G NIC for cluster communications | ||
| 4 | +export ONOS_NIC="10.254.1.*" | ||
| 5 | + | ||
| 6 | +# ONOS Test proxy | ||
| 7 | +export OCT=10.254.1.200 | ||
| 8 | + | ||
| 9 | +# Use the 1G NICs for external access | ||
| 10 | +export OC1=10.254.1.207 | ||
| 11 | +export OC2=10.254.1.202 | ||
| 12 | +export OC3=10.254.1.203 | ||
| 13 | +export OC4=10.254.1.204 | ||
| 14 | +export OC5=10.254.1.206 | ||
| 15 | + | ||
| 16 | +export OCI=${OC1} | ||
| 17 | + | ||
| 18 | +export ONOS_FEATURES=webconsole,onos-api,onos-core,onos-cli,onos-rest,onos-null |
| 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 | -package org.onosproject.ui.impl; | ||
| 17 | - | ||
| 18 | -import com.fasterxml.jackson.databind.ObjectMapper; | ||
| 19 | -import com.fasterxml.jackson.databind.node.ArrayNode; | ||
| 20 | -import com.fasterxml.jackson.databind.node.ObjectNode; | ||
| 21 | -import com.google.common.collect.ImmutableSet; | ||
| 22 | -import org.onlab.osgi.ServiceDirectory; | ||
| 23 | -import org.onosproject.cluster.ClusterService; | ||
| 24 | -import org.onosproject.cluster.ControllerNode; | ||
| 25 | -import org.onosproject.ui.UiConnection; | ||
| 26 | -import org.onosproject.ui.UiMessageHandler; | ||
| 27 | - | ||
| 28 | -import java.util.ArrayList; | ||
| 29 | -import java.util.Collections; | ||
| 30 | -import java.util.Comparator; | ||
| 31 | -import java.util.List; | ||
| 32 | - | ||
| 33 | - | ||
| 34 | -/** | ||
| 35 | - * Facility for creating and sending initial bootstrap message to the GUI. | ||
| 36 | - */ | ||
| 37 | -public class BootstrapMessageHandler extends UiMessageHandler { | ||
| 38 | - | ||
| 39 | - private static final String BOOTSTRAP = "bootstrap"; | ||
| 40 | - | ||
| 41 | - private static final Comparator<? super ControllerNode> NODE_COMPARATOR = | ||
| 42 | - new Comparator<ControllerNode>() { | ||
| 43 | - @Override | ||
| 44 | - public int compare(ControllerNode o1, ControllerNode o2) { | ||
| 45 | - return o1.id().toString().compareTo(o2.id().toString()); | ||
| 46 | - } | ||
| 47 | - }; | ||
| 48 | - | ||
| 49 | - private final ObjectMapper mapper = new ObjectMapper(); | ||
| 50 | - | ||
| 51 | - private ClusterService clusterService; | ||
| 52 | - | ||
| 53 | - // TODO: ClusterEventListener - update GUI when instances come or go... | ||
| 54 | - | ||
| 55 | - /** | ||
| 56 | - * Creates a new bootstrap message handler for bootstrapping the GUI. | ||
| 57 | - */ | ||
| 58 | - protected BootstrapMessageHandler() { | ||
| 59 | - super(ImmutableSet.of(BOOTSTRAP)); | ||
| 60 | - } | ||
| 61 | - | ||
| 62 | - @Override | ||
| 63 | - public void init(UiConnection connection, ServiceDirectory directory) { | ||
| 64 | - super.init(connection, directory); | ||
| 65 | - clusterService = directory.get(ClusterService.class); | ||
| 66 | - | ||
| 67 | - // Obtain list of cluster nodes and send bootstrap message to GUI | ||
| 68 | - List<ControllerNode> nodes = new ArrayList<>(clusterService.getNodes()); | ||
| 69 | - Collections.sort(nodes, NODE_COMPARATOR); | ||
| 70 | - | ||
| 71 | - ObjectNode payload = mapper.createObjectNode(); | ||
| 72 | - | ||
| 73 | - ArrayNode anode = mapper.createArrayNode(); | ||
| 74 | - for (ControllerNode node : nodes) { | ||
| 75 | - anode.add(clusterNodeData(node)); | ||
| 76 | - } | ||
| 77 | - payload.set("instances", anode); | ||
| 78 | - connection.sendMessage(envelope(BOOTSTRAP, 0, payload)); | ||
| 79 | - } | ||
| 80 | - | ||
| 81 | - private ObjectNode clusterNodeData(ControllerNode node) { | ||
| 82 | - return mapper.createObjectNode() | ||
| 83 | - .put("id", node.id().toString()) | ||
| 84 | - .put("ip", node.ip().toString()) | ||
| 85 | - .put("uiAttached", node.equals(clusterService.getLocalNode())); | ||
| 86 | - } | ||
| 87 | - | ||
| 88 | - | ||
| 89 | - @Override | ||
| 90 | - public void process(ObjectNode message) { | ||
| 91 | - // We registered for "bootstrap" events, but we don't expect | ||
| 92 | - // the GUI to send us any; it was just that we had to define a | ||
| 93 | - // non-empty set of events that we handle, in the constructor. | ||
| 94 | - } | ||
| 95 | - | ||
| 96 | -} |
| ... | @@ -305,7 +305,7 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler { | ... | @@ -305,7 +305,7 @@ public abstract class TopologyViewMessageHandlerBase extends UiMessageHandler { |
| 305 | .put("id", node.id().toString()) | 305 | .put("id", node.id().toString()) |
| 306 | .put("ip", node.ip().toString()) | 306 | .put("ip", node.ip().toString()) |
| 307 | .put("online", clusterService.getState(node.id()) == ACTIVE) | 307 | .put("online", clusterService.getState(node.id()) == ACTIVE) |
| 308 | - .put("uiAttached", event.subject().equals(clusterService.getLocalNode())) | 308 | + .put("uiAttached", node.equals(clusterService.getLocalNode())) |
| 309 | .put("switches", switchCount); | 309 | .put("switches", switchCount); |
| 310 | 310 | ||
| 311 | ArrayNode labels = mapper.createArrayNode(); | 311 | ArrayNode labels = mapper.createArrayNode(); | ... | ... |
| ... | @@ -61,7 +61,6 @@ public class UiExtensionManager implements UiExtensionService { | ... | @@ -61,7 +61,6 @@ public class UiExtensionManager implements UiExtensionService { |
| 61 | new UiView("device", "Devices")); | 61 | new UiView("device", "Devices")); |
| 62 | UiMessageHandlerFactory messageHandlerFactory = | 62 | UiMessageHandlerFactory messageHandlerFactory = |
| 63 | () -> ImmutableList.of( | 63 | () -> ImmutableList.of( |
| 64 | - new BootstrapMessageHandler(), | ||
| 65 | new TopologyViewMessageHandler() | 64 | new TopologyViewMessageHandler() |
| 66 | ); | 65 | ); |
| 67 | return new UiExtension(coreViews, messageHandlerFactory, "core", | 66 | return new UiExtension(coreViews, messageHandlerFactory, "core", | ... | ... |
| ... | @@ -16,9 +16,12 @@ | ... | @@ -16,9 +16,12 @@ |
| 16 | package org.onosproject.ui.impl; | 16 | package org.onosproject.ui.impl; |
| 17 | 17 | ||
| 18 | import com.fasterxml.jackson.databind.ObjectMapper; | 18 | import com.fasterxml.jackson.databind.ObjectMapper; |
| 19 | +import com.fasterxml.jackson.databind.node.ArrayNode; | ||
| 19 | import com.fasterxml.jackson.databind.node.ObjectNode; | 20 | import com.fasterxml.jackson.databind.node.ObjectNode; |
| 20 | import org.eclipse.jetty.websocket.WebSocket; | 21 | import org.eclipse.jetty.websocket.WebSocket; |
| 21 | import org.onlab.osgi.ServiceDirectory; | 22 | import org.onlab.osgi.ServiceDirectory; |
| 23 | +import org.onosproject.cluster.ClusterService; | ||
| 24 | +import org.onosproject.cluster.ControllerNode; | ||
| 22 | import org.onosproject.ui.UiConnection; | 25 | import org.onosproject.ui.UiConnection; |
| 23 | import org.onosproject.ui.UiExtensionService; | 26 | import org.onosproject.ui.UiExtensionService; |
| 24 | import org.onosproject.ui.UiMessageHandler; | 27 | import org.onosproject.ui.UiMessageHandler; |
| ... | @@ -99,6 +102,7 @@ public class UiWebSocket | ... | @@ -99,6 +102,7 @@ public class UiWebSocket |
| 99 | this.connection = connection; | 102 | this.connection = connection; |
| 100 | this.control = (FrameConnection) connection; | 103 | this.control = (FrameConnection) connection; |
| 101 | createHandlers(); | 104 | createHandlers(); |
| 105 | + sendInstanceData(); | ||
| 102 | } | 106 | } |
| 103 | 107 | ||
| 104 | @Override | 108 | @Override |
| ... | @@ -143,6 +147,18 @@ public class UiWebSocket | ... | @@ -143,6 +147,18 @@ public class UiWebSocket |
| 143 | } | 147 | } |
| 144 | } | 148 | } |
| 145 | 149 | ||
| 150 | + @Override | ||
| 151 | + public void sendMessage(String type, long sid, ObjectNode payload) { | ||
| 152 | + ObjectNode message = mapper.createObjectNode(); | ||
| 153 | + message.put("event", type); | ||
| 154 | + if (sid > 0) { | ||
| 155 | + message.put("sid", sid); | ||
| 156 | + } | ||
| 157 | + message.set("payload", payload); | ||
| 158 | + sendMessage(message); | ||
| 159 | + | ||
| 160 | + } | ||
| 161 | + | ||
| 146 | // Creates new message handlers. | 162 | // Creates new message handlers. |
| 147 | private void createHandlers() { | 163 | private void createHandlers() { |
| 148 | handlers = new HashMap<>(); | 164 | handlers = new HashMap<>(); |
| ... | @@ -163,5 +179,24 @@ public class UiWebSocket | ... | @@ -163,5 +179,24 @@ public class UiWebSocket |
| 163 | handlers.forEach((type, handler) -> handler.destroy()); | 179 | handlers.forEach((type, handler) -> handler.destroy()); |
| 164 | handlers.clear(); | 180 | handlers.clear(); |
| 165 | } | 181 | } |
| 182 | + | ||
| 183 | + // Sends cluster node/instance information to allow GUI to fail-over. | ||
| 184 | + private void sendInstanceData() { | ||
| 185 | + ClusterService service = directory.get(ClusterService.class); | ||
| 186 | + ArrayNode instances = mapper.createArrayNode(); | ||
| 187 | + | ||
| 188 | + for (ControllerNode node : service.getNodes()) { | ||
| 189 | + ObjectNode instance = mapper.createObjectNode() | ||
| 190 | + .put("id", node.id().toString()) | ||
| 191 | + .put("ip", node.ip().toString()) | ||
| 192 | + .put("uiAttached", node.equals(service.getLocalNode())); | ||
| 193 | + instances.add(instance); | ||
| 194 | + } | ||
| 195 | + | ||
| 196 | + ObjectNode payload = mapper.createObjectNode(); | ||
| 197 | + payload.set("instances", instances); | ||
| 198 | + sendMessage("onosInstances", 0, payload); | ||
| 199 | + } | ||
| 200 | + | ||
| 166 | } | 201 | } |
| 167 | 202 | ... | ... |
| ... | @@ -29,8 +29,14 @@ | ... | @@ -29,8 +29,14 @@ |
| 29 | sid = 0, // event sequence identifier | 29 | sid = 0, // event sequence identifier |
| 30 | handlers = {}, // event handler bindings | 30 | handlers = {}, // event handler bindings |
| 31 | pendingEvents = [], // events TX'd while socket not up | 31 | pendingEvents = [], // events TX'd while socket not up |
| 32 | - url; // web socket URL | 32 | + url, // web socket URL |
| 33 | + instances = []; | ||
| 33 | 34 | ||
| 35 | + var builtinHandlers = { | ||
| 36 | + onosInstances: function (data) { | ||
| 37 | + instances = data.instances; | ||
| 38 | + } | ||
| 39 | + } | ||
| 34 | 40 | ||
| 35 | // ========================== | 41 | // ========================== |
| 36 | // === Web socket callbacks | 42 | // === Web socket callbacks |
| ... | @@ -186,6 +192,11 @@ | ... | @@ -186,6 +192,11 @@ |
| 186 | wsock = _wsock_; | 192 | wsock = _wsock_; |
| 187 | vs = _vs_; | 193 | vs = _vs_; |
| 188 | 194 | ||
| 195 | + // Bind instance handlers | ||
| 196 | + bindHandlers({ | ||
| 197 | + onosInstances: builtinHandlers | ||
| 198 | + }); | ||
| 199 | + | ||
| 189 | return { | 200 | return { |
| 190 | resetSid: resetSid, | 201 | resetSid: resetSid, |
| 191 | createWebSocket: createWebSocket, | 202 | createWebSocket: createWebSocket, | ... | ... |
-
Please register or login to post a comment