Simon Hunt
Committed by Gerrit Code Review

TopoRegions: created skeleton Topo2 UI view for development of the "region-aware" topology.

 - Added initial event generation (layout/region/ etc.) -- WIP

Change-Id: I2f93eea7505ff0400085d7f67491f6b61231cb86
...@@ -89,6 +89,17 @@ public abstract class RequestHandler { ...@@ -89,6 +89,17 @@ public abstract class RequestHandler {
89 89
90 /** 90 /**
91 * Sends a message back to the client. 91 * Sends a message back to the client.
92 + *
93 + * @param eventType message event type
94 + * @param payload message payload
95 + */
96 + protected void sendMessage(String eventType, ObjectNode payload) {
97 + // TODO: remove sid
98 + parent.connection().sendMessage(eventType, 0, payload);
99 + }
100 +
101 + /**
102 + * Sends a message back to the client.
92 * Here, the message is preformatted; the assumption is it has its 103 * Here, the message is preformatted; the assumption is it has its
93 * eventType, sid and payload attributes already filled in. 104 * eventType, sid and payload attributes already filled in.
94 * 105 *
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
17 package org.onosproject.ui.model.topo; 17 package org.onosproject.ui.model.topo;
18 18
19 import com.google.common.base.MoreObjects; 19 import com.google.common.base.MoreObjects;
20 +import org.onosproject.cluster.NodeId;
20 import org.onosproject.net.Device; 21 import org.onosproject.net.Device;
21 import org.onosproject.net.DeviceId; 22 import org.onosproject.net.DeviceId;
22 import org.onosproject.net.region.RegionId; 23 import org.onosproject.net.region.RegionId;
...@@ -30,6 +31,8 @@ public class UiDevice extends UiNode { ...@@ -30,6 +31,8 @@ public class UiDevice extends UiNode {
30 private final Device device; 31 private final Device device;
31 32
32 private RegionId regionId; 33 private RegionId regionId;
34 + private NodeId masterId;
35 + private boolean online;
33 36
34 /** 37 /**
35 * Creates a new UI device. 38 * Creates a new UI device.
...@@ -51,6 +54,24 @@ public class UiDevice extends UiNode { ...@@ -51,6 +54,24 @@ public class UiDevice extends UiNode {
51 this.regionId = regionId; 54 this.regionId = regionId;
52 } 55 }
53 56
57 + /**
58 + * Sets the ID of the controller node that holds mastership for this device.
59 + *
60 + * @param masterId master identifier
61 + */
62 + public void setMasterId(NodeId masterId) {
63 + this.masterId = masterId;
64 + }
65 +
66 + /**
67 + * Sets a flag indicating whether the backing device is online.
68 + *
69 + * @param online boolen flag
70 + */
71 + public void setOnline(boolean online) {
72 + this.online = online;
73 + }
74 +
54 @Override 75 @Override
55 public String toString() { 76 public String toString() {
56 return MoreObjects.toStringHelper(this) 77 return MoreObjects.toStringHelper(this)
...@@ -104,4 +125,32 @@ public class UiDevice extends UiNode { ...@@ -104,4 +125,32 @@ public class UiDevice extends UiNode {
104 public UiRegion uiRegion() { 125 public UiRegion uiRegion() {
105 return topology.findRegion(regionId); 126 return topology.findRegion(regionId);
106 } 127 }
128 +
129 + /**
130 + * Returns a string representation of the type of the backing device.
131 + *
132 + * @return the device type
133 + */
134 + public String type() {
135 + return device.type().toString().toLowerCase();
136 + }
137 +
138 + /**
139 + * Returns a boolean indicating whether the backing device is online.
140 + *
141 + * @return true if device is online, false otherwise
142 + */
143 + public boolean isOnline() {
144 + return online;
145 + }
146 +
147 + /**
148 + * Returns the identifier for the cluster member that has
149 + * mastership over this device.
150 + *
151 + * @return master cluster member identifier
152 + */
153 + public NodeId master() {
154 + return masterId;
155 + }
107 } 156 }
......
...@@ -20,4 +20,41 @@ package org.onosproject.ui.model.topo; ...@@ -20,4 +20,41 @@ package org.onosproject.ui.model.topo;
20 * Represents a node drawn on the topology view (region, device, host). 20 * Represents a node drawn on the topology view (region, device, host).
21 */ 21 */
22 abstract class UiNode extends UiElement { 22 abstract class UiNode extends UiElement {
23 +
24 + /**
25 + * Default "layer" tag.
26 + */
27 + public static final String LAYER_DEFAULT = "def";
28 +
29 + /**
30 + * Packet layer tag.
31 + */
32 + public static final String LAYER_PACKET = "pkt";
33 +
34 + /**
35 + * Optical layer tag.
36 + */
37 + public static final String LAYER_OPTICAL = "opt";
38 +
39 +
40 + private String layer = LAYER_DEFAULT;
41 +
42 + /**
43 + * Returns the tag for the "layer" that the node should be rendered in
44 + * when viewed in the oblique view.
45 + *
46 + * @return the node's layer
47 + */
48 + public String layer() {
49 + return layer;
50 + }
51 +
52 + /**
53 + * Sets this node's "layer", for layered rendering.
54 + *
55 + * @param layerTag the layer tag to set
56 + */
57 + public void setLayer(String layerTag) {
58 + layer = layerTag;
59 + }
23 } 60 }
......
...@@ -22,7 +22,10 @@ import org.onosproject.net.HostId; ...@@ -22,7 +22,10 @@ import org.onosproject.net.HostId;
22 import org.onosproject.net.region.Region; 22 import org.onosproject.net.region.Region;
23 import org.onosproject.net.region.RegionId; 23 import org.onosproject.net.region.RegionId;
24 24
25 +import java.util.ArrayList;
26 +import java.util.Collections;
25 import java.util.HashSet; 27 import java.util.HashSet;
28 +import java.util.List;
26 import java.util.Set; 29 import java.util.Set;
27 30
28 import static com.google.common.base.MoreObjects.toStringHelper; 31 import static com.google.common.base.MoreObjects.toStringHelper;
...@@ -37,6 +40,8 @@ public class UiRegion extends UiNode { ...@@ -37,6 +40,8 @@ public class UiRegion extends UiNode {
37 private final Set<HostId> hostIds = new HashSet<>(); 40 private final Set<HostId> hostIds = new HashSet<>();
38 private final Set<UiLinkId> uiLinkIds = new HashSet<>(); 41 private final Set<UiLinkId> uiLinkIds = new HashSet<>();
39 42
43 + private final List<String> layerOrder = new ArrayList<>();
44 +
40 private final UiTopology topology; 45 private final UiTopology topology;
41 46
42 private final Region region; 47 private final Region region;
...@@ -50,6 +55,8 @@ public class UiRegion extends UiNode { ...@@ -50,6 +55,8 @@ public class UiRegion extends UiNode {
50 public UiRegion(UiTopology topology, Region region) { 55 public UiRegion(UiTopology topology, Region region) {
51 this.topology = topology; 56 this.topology = topology;
52 this.region = region; 57 this.region = region;
58 + // unless told otherwise, we'll use a single, default layer
59 + layerOrder.add(UiNode.LAYER_DEFAULT);
53 } 60 }
54 61
55 @Override 62 @Override
...@@ -60,6 +67,17 @@ public class UiRegion extends UiNode { ...@@ -60,6 +67,17 @@ public class UiRegion extends UiNode {
60 } 67 }
61 68
62 /** 69 /**
70 + * Sets the layer order for this region.
71 + * Typically, the {@code UiNode.LAYER_*} constants will be used here.
72 + *
73 + * @param layers the layers
74 + */
75 + public void setLayerOrder(String... layers) {
76 + layerOrder.clear();
77 + Collections.addAll(layerOrder, layers);
78 + }
79 +
80 + /**
63 * Returns the identity of the region. 81 * Returns the identity of the region.
64 * 82 *
65 * @return region ID 83 * @return region ID
...@@ -170,4 +188,19 @@ public class UiRegion extends UiNode { ...@@ -170,4 +188,19 @@ public class UiRegion extends UiNode {
170 public Set<UiLink> links() { 188 public Set<UiLink> links() {
171 return topology.linkSet(uiLinkIds); 189 return topology.linkSet(uiLinkIds);
172 } 190 }
191 +
192 + /**
193 + * Returns the order in which layers should be rendered. Lower layers
194 + * come earlier in the list. For example, to indicate that nodes in the
195 + * optical layer should be rendered "below" nodes in the packet layer,
196 + * this method should return:
197 + * <pre>
198 + * [UiNode.LAYER_OPTICAL, UiNode.LAYER_PACKET]
199 + * </pre>
200 + *
201 + * @return layer ordering
202 + */
203 + public List<String> layerOrder() {
204 + return Collections.unmodifiableList(layerOrder);
205 + }
173 } 206 }
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
17 package org.onosproject.ui.model.topo; 17 package org.onosproject.ui.model.topo;
18 18
19 import org.onosproject.net.region.Region; 19 import org.onosproject.net.region.Region;
20 +import org.onosproject.net.region.RegionId;
20 21
21 /** 22 /**
22 * Represents a specific "subset" of the UI model of the network topology 23 * Represents a specific "subset" of the UI model of the network topology
...@@ -41,6 +42,11 @@ public class UiTopoLayout { ...@@ -41,6 +42,11 @@ public class UiTopoLayout {
41 this.parent = parent; 42 this.parent = parent;
42 } 43 }
43 44
45 + @Override
46 + public String toString() {
47 + return "{UiTopoLayout: " + id + "}";
48 + }
49 +
44 /** 50 /**
45 * Returns the UI layout identifier. 51 * Returns the UI layout identifier.
46 * 52 *
...@@ -51,7 +57,8 @@ public class UiTopoLayout { ...@@ -51,7 +57,8 @@ public class UiTopoLayout {
51 } 57 }
52 58
53 /** 59 /**
54 - * Returns the backing region with which this layout is associated. 60 + * Returns the backing region with which this layout is associated. Note
61 + * that this may be null (for the root layout).
55 * 62 *
56 * @return backing region 63 * @return backing region
57 */ 64 */
...@@ -60,6 +67,16 @@ public class UiTopoLayout { ...@@ -60,6 +67,16 @@ public class UiTopoLayout {
60 } 67 }
61 68
62 /** 69 /**
70 + * Returns the identifier of the backing region. Will be null if the
71 + * region is null.
72 + *
73 + * @return backing region identifier
74 + */
75 + public RegionId regionId() {
76 + return region == null ? null : region.id();
77 + }
78 +
79 + /**
63 * Returns the parent layout identifier. 80 * Returns the parent layout identifier.
64 * 81 *
65 * @return parent layout identifier 82 * @return parent layout identifier
......
...@@ -23,8 +23,12 @@ import org.onosproject.net.region.RegionId; ...@@ -23,8 +23,12 @@ import org.onosproject.net.region.RegionId;
23 import org.slf4j.Logger; 23 import org.slf4j.Logger;
24 import org.slf4j.LoggerFactory; 24 import org.slf4j.LoggerFactory;
25 25
26 +import java.util.ArrayList;
27 +import java.util.Collections;
28 +import java.util.Comparator;
26 import java.util.HashMap; 29 import java.util.HashMap;
27 import java.util.HashSet; 30 import java.util.HashSet;
31 +import java.util.List;
28 import java.util.Map; 32 import java.util.Map;
29 import java.util.Set; 33 import java.util.Set;
30 34
...@@ -46,6 +50,9 @@ public class UiTopology extends UiElement { ...@@ -46,6 +50,9 @@ public class UiTopology extends UiElement {
46 50
47 private static final Logger log = LoggerFactory.getLogger(UiTopology.class); 51 private static final Logger log = LoggerFactory.getLogger(UiTopology.class);
48 52
53 + private static final Comparator<UiClusterMember> CLUSTER_MEMBER_COMPARATOR =
54 + (o1, o2) -> o1.idAsString().compareTo(o2.idAsString());
55 +
49 56
50 // top level mappings of topology elements by ID 57 // top level mappings of topology elements by ID
51 private final Map<NodeId, UiClusterMember> cnodeLookup = new HashMap<>(); 58 private final Map<NodeId, UiClusterMember> cnodeLookup = new HashMap<>();
...@@ -84,6 +91,18 @@ public class UiTopology extends UiElement { ...@@ -84,6 +91,18 @@ public class UiTopology extends UiElement {
84 linkLookup.clear(); 91 linkLookup.clear();
85 } 92 }
86 93
94 +
95 + /**
96 + * Returns all the cluster members, sorted by their ID.
97 + *
98 + * @return all cluster members
99 + */
100 + public List<UiClusterMember> allClusterMembers() {
101 + List<UiClusterMember> members = new ArrayList<>(cnodeLookup.values());
102 + Collections.sort(members, CLUSTER_MEMBER_COMPARATOR);
103 + return members;
104 + }
105 +
87 /** 106 /**
88 * Returns the cluster member with the given identifier, or null if no 107 * Returns the cluster member with the given identifier, or null if no
89 * such member exists. 108 * such member exists.
......
...@@ -185,7 +185,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase { ...@@ -185,7 +185,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase {
185 private TimerTask summaryTask = null; 185 private TimerTask summaryTask = null;
186 private boolean summaryRunning = false; 186 private boolean summaryRunning = false;
187 187
188 - private boolean listenersRemoved = false; 188 + private volatile boolean listenersRemoved = false;
189 189
190 190
191 @Override 191 @Override
......
...@@ -32,7 +32,6 @@ import com.google.common.collect.ImmutableMap; ...@@ -32,7 +32,6 @@ import com.google.common.collect.ImmutableMap;
32 import com.google.common.collect.ImmutableSet; 32 import com.google.common.collect.ImmutableSet;
33 import com.google.common.collect.Lists; 33 import com.google.common.collect.Lists;
34 import com.google.common.collect.Maps; 34 import com.google.common.collect.Maps;
35 -
36 import org.apache.felix.scr.annotations.Activate; 35 import org.apache.felix.scr.annotations.Activate;
37 import org.apache.felix.scr.annotations.Component; 36 import org.apache.felix.scr.annotations.Component;
38 import org.apache.felix.scr.annotations.Deactivate; 37 import org.apache.felix.scr.annotations.Deactivate;
...@@ -51,11 +50,12 @@ import org.onosproject.ui.UiExtension; ...@@ -51,11 +50,12 @@ import org.onosproject.ui.UiExtension;
51 import org.onosproject.ui.UiExtensionService; 50 import org.onosproject.ui.UiExtensionService;
52 import org.onosproject.ui.UiMessageHandlerFactory; 51 import org.onosproject.ui.UiMessageHandlerFactory;
53 import org.onosproject.ui.UiPreferencesService; 52 import org.onosproject.ui.UiPreferencesService;
54 -import org.onosproject.ui.UiTopoOverlayFactory; 53 +import org.onosproject.ui.UiTopoMap;
55 import org.onosproject.ui.UiTopoMapFactory; 54 import org.onosproject.ui.UiTopoMapFactory;
55 +import org.onosproject.ui.UiTopoOverlayFactory;
56 import org.onosproject.ui.UiView; 56 import org.onosproject.ui.UiView;
57 import org.onosproject.ui.UiViewHidden; 57 import org.onosproject.ui.UiViewHidden;
58 -import org.onosproject.ui.UiTopoMap; 58 +import org.onosproject.ui.impl.topo.Topo2ViewMessageHandler;
59 import org.slf4j.Logger; 59 import org.slf4j.Logger;
60 import org.slf4j.LoggerFactory; 60 import org.slf4j.LoggerFactory;
61 61
...@@ -120,7 +120,8 @@ public class UiExtensionManager ...@@ -120,7 +120,8 @@ public class UiExtensionManager
120 private final ObjectMapper mapper = new ObjectMapper(); 120 private final ObjectMapper mapper = new ObjectMapper();
121 121
122 private final ExecutorService eventHandlingExecutor = 122 private final ExecutorService eventHandlingExecutor =
123 - Executors.newSingleThreadExecutor(Tools.groupedThreads("onos/ui-ext-manager", "event-handler", log)); 123 + Executors.newSingleThreadExecutor(
124 + Tools.groupedThreads("onos/ui-ext-manager", "event-handler", log));
124 125
125 // Creates core UI extension 126 // Creates core UI extension
126 private UiExtension createCoreExtension() { 127 private UiExtension createCoreExtension() {
...@@ -130,6 +131,10 @@ public class UiExtensionManager ...@@ -130,6 +131,10 @@ public class UiExtensionManager
130 new UiView(PLATFORM, "cluster", "Cluster Nodes", "nav_cluster"), 131 new UiView(PLATFORM, "cluster", "Cluster Nodes", "nav_cluster"),
131 new UiView(PLATFORM, "processor", "Packet Processors", "nav_processors"), 132 new UiView(PLATFORM, "processor", "Packet Processors", "nav_processors"),
132 new UiView(NETWORK, "topo", "Topology", "nav_topo"), 133 new UiView(NETWORK, "topo", "Topology", "nav_topo"),
134 +
135 + // FIXME: leave commented out for now, while still under development
136 +// new UiView(NETWORK, "topo2", "New-Topo"),
137 +
133 new UiView(NETWORK, "device", "Devices", "nav_devs"), 138 new UiView(NETWORK, "device", "Devices", "nav_devs"),
134 new UiViewHidden("flow"), 139 new UiViewHidden("flow"),
135 new UiViewHidden("port"), 140 new UiViewHidden("port"),
...@@ -145,6 +150,7 @@ public class UiExtensionManager ...@@ -145,6 +150,7 @@ public class UiExtensionManager
145 () -> ImmutableList.of( 150 () -> ImmutableList.of(
146 new UserPreferencesMessageHandler(), 151 new UserPreferencesMessageHandler(),
147 new TopologyViewMessageHandler(), 152 new TopologyViewMessageHandler(),
153 + new Topo2ViewMessageHandler(),
148 new MapSelectorMessageHandler(), 154 new MapSelectorMessageHandler(),
149 new DeviceViewMessageHandler(), 155 new DeviceViewMessageHandler(),
150 new LinkViewMessageHandler(), 156 new LinkViewMessageHandler(),
...@@ -196,11 +202,11 @@ public class UiExtensionManager ...@@ -196,11 +202,11 @@ public class UiExtensionManager
196 @Activate 202 @Activate
197 public void activate() { 203 public void activate() {
198 Serializer serializer = Serializer.using(KryoNamespaces.API, 204 Serializer serializer = Serializer.using(KryoNamespaces.API,
199 - ObjectNode.class, ArrayNode.class, 205 + ObjectNode.class, ArrayNode.class,
200 - JsonNodeFactory.class, LinkedHashMap.class, 206 + JsonNodeFactory.class, LinkedHashMap.class,
201 - TextNode.class, BooleanNode.class, 207 + TextNode.class, BooleanNode.class,
202 - LongNode.class, DoubleNode.class, ShortNode.class, 208 + LongNode.class, DoubleNode.class, ShortNode.class,
203 - IntNode.class, NullNode.class); 209 + IntNode.class, NullNode.class);
204 210
205 prefsConsistentMap = storageService.<String, ObjectNode>consistentMapBuilder() 211 prefsConsistentMap = storageService.<String, ObjectNode>consistentMapBuilder()
206 .withName(ONOS_USER_PREFERENCES) 212 .withName(ONOS_USER_PREFERENCES)
......
...@@ -92,7 +92,7 @@ public class UiWebSocket ...@@ -92,7 +92,7 @@ public class UiWebSocket
92 this.userName = userName; 92 this.userName = userName;
93 this.topoSession = 93 this.topoSession =
94 new UiTopoSession(this, directory.get(UiSharedTopologyModel.class), 94 new UiTopoSession(this, directory.get(UiSharedTopologyModel.class),
95 - directory.get(UiTopoLayoutService.class)); 95 + directory.get(UiTopoLayoutService.class));
96 } 96 }
97 97
98 @Override 98 @Override
...@@ -122,6 +122,15 @@ public class UiWebSocket ...@@ -122,6 +122,15 @@ public class UiWebSocket
122 } 122 }
123 123
124 /** 124 /**
125 + * Provides a reference to the topology session.
126 + *
127 + * @return topo session reference
128 + */
129 + public UiTopoSession topoSession() {
130 + return topoSession;
131 + }
132 +
133 + /**
125 * Issues a close on the connection. 134 * Issues a close on the connection.
126 */ 135 */
127 synchronized void close() { 136 synchronized void close() {
...@@ -175,7 +184,7 @@ public class UiWebSocket ...@@ -175,7 +184,7 @@ public class UiWebSocket
175 topoSession.destroy(); 184 topoSession.destroy();
176 destroyHandlersAndOverlays(); 185 destroyHandlersAndOverlays();
177 log.info("GUI client disconnected [close-code={}, message={}]", 186 log.info("GUI client disconnected [close-code={}, message={}]",
178 - closeCode, message); 187 + closeCode, message);
179 } 188 }
180 189
181 @Override 190 @Override
...@@ -186,13 +195,13 @@ public class UiWebSocket ...@@ -186,13 +195,13 @@ public class UiWebSocket
186 195
187 @Override 196 @Override
188 public void onMessage(String data) { 197 public void onMessage(String data) {
189 - log.debug("onMessage: {}", data);
190 lastActive = System.currentTimeMillis(); 198 lastActive = System.currentTimeMillis();
191 try { 199 try {
192 ObjectNode message = (ObjectNode) mapper.reader().readTree(data); 200 ObjectNode message = (ObjectNode) mapper.reader().readTree(data);
193 String type = message.path(EVENT).asText(UNKNOWN); 201 String type = message.path(EVENT).asText(UNKNOWN);
194 UiMessageHandler handler = handlers.get(type); 202 UiMessageHandler handler = handlers.get(type);
195 if (handler != null) { 203 if (handler != null) {
204 + log.debug("RX message: {}", message);
196 handler.process(message); 205 handler.process(message);
197 } else { 206 } else {
198 log.warn("No GUI message handler for type {}", type); 207 log.warn("No GUI message handler for type {}", type);
...@@ -208,6 +217,7 @@ public class UiWebSocket ...@@ -208,6 +217,7 @@ public class UiWebSocket
208 try { 217 try {
209 if (connection.isOpen()) { 218 if (connection.isOpen()) {
210 connection.sendMessage(message.toString()); 219 connection.sendMessage(message.toString());
220 + log.debug("TX message: {}", message);
211 } 221 }
212 } catch (IOException e) { 222 } catch (IOException e) {
213 log.warn("Unable to send message {} to GUI due to {}", message, e); 223 log.warn("Unable to send message {} to GUI due to {}", message, e);
...@@ -257,7 +267,7 @@ public class UiWebSocket ...@@ -257,7 +267,7 @@ public class UiWebSocket
257 } 267 }
258 }); 268 });
259 log.debug("#handlers = {}, #overlays = {}", handlers.size(), 269 log.debug("#handlers = {}, #overlays = {}", handlers.size(),
260 - overlayCache.size()); 270 + overlayCache.size());
261 } 271 }
262 272
263 // Destroys message handlers. 273 // Destroys message handlers.
...@@ -284,7 +294,7 @@ public class UiWebSocket ...@@ -284,7 +294,7 @@ public class UiWebSocket
284 .put(ID, node.id().toString()) 294 .put(ID, node.id().toString())
285 .put(IP, node.ip().toString()) 295 .put(IP, node.ip().toString())
286 .put(TopoConstants.Glyphs.UI_ATTACHED, 296 .put(TopoConstants.Glyphs.UI_ATTACHED,
287 - node.equals(service.getLocalNode())); 297 + node.equals(service.getLocalNode()));
288 instances.add(instance); 298 instances.add(instance);
289 } 299 }
290 300
......
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;
18 +
19 +import com.fasterxml.jackson.databind.ObjectMapper;
20 +import com.fasterxml.jackson.databind.node.ArrayNode;
21 +import com.fasterxml.jackson.databind.node.ObjectNode;
22 +import org.onlab.osgi.ServiceDirectory;
23 +import org.onosproject.cluster.ClusterService;
24 +import org.onosproject.cluster.NodeId;
25 +import org.onosproject.incubator.net.PortStatisticsService;
26 +import org.onosproject.incubator.net.tunnel.TunnelService;
27 +import org.onosproject.mastership.MastershipService;
28 +import org.onosproject.net.device.DeviceService;
29 +import org.onosproject.net.flow.FlowRuleService;
30 +import org.onosproject.net.host.HostService;
31 +import org.onosproject.net.intent.IntentService;
32 +import org.onosproject.net.link.LinkService;
33 +import org.onosproject.net.region.Region;
34 +import org.onosproject.net.statistic.StatisticService;
35 +import org.onosproject.net.topology.TopologyService;
36 +import org.onosproject.ui.model.topo.UiClusterMember;
37 +import org.onosproject.ui.model.topo.UiDevice;
38 +import org.onosproject.ui.model.topo.UiHost;
39 +import org.onosproject.ui.model.topo.UiLink;
40 +import org.onosproject.ui.model.topo.UiRegion;
41 +import org.onosproject.ui.model.topo.UiTopoLayout;
42 +
43 +import java.util.List;
44 +
45 +import static com.google.common.base.Preconditions.checkNotNull;
46 +
47 +/**
48 + * Facility for creating JSON messages to send to the topology view in the
49 + * Web client.
50 + */
51 +class Topo2Jsonifier {
52 +
53 + private final ObjectMapper mapper = new ObjectMapper();
54 +
55 + private ServiceDirectory directory;
56 + private ClusterService clusterService;
57 + private DeviceService deviceService;
58 + private LinkService linkService;
59 + private HostService hostService;
60 + private MastershipService mastershipService;
61 + private IntentService intentService;
62 + private FlowRuleService flowService;
63 + private StatisticService flowStatsService;
64 + private PortStatisticsService portStatsService;
65 + private TopologyService topologyService;
66 + private TunnelService tunnelService;
67 +
68 +
69 + /**
70 + * Creates an instance with a reference to the services directory, so that
71 + * additional information about network elements may be looked up on
72 + * on the fly.
73 + *
74 + * @param directory service directory
75 + */
76 + Topo2Jsonifier(ServiceDirectory directory) {
77 + this.directory = checkNotNull(directory, "Directory cannot be null");
78 +
79 + clusterService = directory.get(ClusterService.class);
80 + deviceService = directory.get(DeviceService.class);
81 + linkService = directory.get(LinkService.class);
82 + hostService = directory.get(HostService.class);
83 + mastershipService = directory.get(MastershipService.class);
84 + intentService = directory.get(IntentService.class);
85 + flowService = directory.get(FlowRuleService.class);
86 + flowStatsService = directory.get(StatisticService.class);
87 + portStatsService = directory.get(PortStatisticsService.class);
88 + topologyService = directory.get(TopologyService.class);
89 + tunnelService = directory.get(TunnelService.class);
90 +
91 + }
92 +
93 + private ObjectNode objectNode() {
94 + return mapper.createObjectNode();
95 + }
96 +
97 + private ArrayNode arrayNode() {
98 + return mapper.createArrayNode();
99 + }
100 +
101 + private String nullIsEmpty(Object o) {
102 + return o == null ? "" : o.toString();
103 + }
104 +
105 +
106 + /**
107 + * Returns a JSON representation of the cluster members (ONOS instances).
108 + *
109 + * @param instances the instance model objects
110 + * @return a JSON representation of the data
111 + */
112 + ObjectNode instances(List<UiClusterMember> instances) {
113 + NodeId local = clusterService.getLocalNode().id();
114 + ObjectNode payload = objectNode();
115 +
116 + ArrayNode members = arrayNode();
117 + payload.set("members", members);
118 + for (UiClusterMember member : instances) {
119 + members.add(json(member, member.id().equals(local)));
120 + }
121 +
122 + return payload;
123 + }
124 +
125 + private ObjectNode json(UiClusterMember member, boolean isUiAttached) {
126 + return objectNode()
127 + .put("id", member.id().toString())
128 + .put("ip", member.ip().toString())
129 + .put("online", member.isOnline())
130 + .put("ready", member.isReady())
131 + .put("uiAttached", isUiAttached)
132 + .put("switches", member.deviceCount());
133 + }
134 +
135 + /**
136 + * Returns a JSON representation of the layout to use for displaying in
137 + * the topology view.
138 + *
139 + * @param layout the layout to transform
140 + * @return a JSON representation of the data
141 + */
142 + ObjectNode layout(UiTopoLayout layout) {
143 + return objectNode()
144 + .put("id", layout.id().toString())
145 + .put("parent", nullIsEmpty(layout.parent()))
146 + .put("region", nullIsEmpty(layout.regionId()))
147 + .put("regionName", regionName(layout.region()));
148 + }
149 +
150 + private String regionName(Region region) {
151 + return region == null ? "" : region.name();
152 + }
153 +
154 + /**
155 + * Returns a JSON representation of the region to display in the topology
156 + * view.
157 + *
158 + * @param region the region to transform to JSON
159 + * @return a JSON representation of the data
160 + */
161 + ObjectNode region(UiRegion region) {
162 + ObjectNode payload = objectNode();
163 +
164 + if (region == null) {
165 + payload.put("note", "no-region");
166 + return payload;
167 + }
168 +
169 + payload.put("id", region.id().toString());
170 +
171 + ArrayNode layerOrder = arrayNode();
172 + payload.set("layerOrder", layerOrder);
173 + region.layerOrder().forEach(layerOrder::add);
174 +
175 + ArrayNode devices = arrayNode();
176 + payload.set("devices", devices);
177 + for (UiDevice device : region.devices()) {
178 + devices.add(json(device));
179 + }
180 +
181 + ArrayNode hosts = arrayNode();
182 + payload.set("hosts", hosts);
183 + for (UiHost host : region.hosts()) {
184 + hosts.add(json(host));
185 + }
186 +
187 + ArrayNode links = arrayNode();
188 + payload.set("links", links);
189 + for (UiLink link : region.links()) {
190 + links.add(json(link));
191 + }
192 +
193 + return payload;
194 + }
195 +
196 + private ObjectNode json(UiDevice device) {
197 + ObjectNode node = objectNode()
198 + .put("id", device.id().toString())
199 + .put("type", device.type())
200 + .put("online", device.isOnline())
201 + .put("master", device.master().toString())
202 + .put("layer", device.layer());
203 +
204 + // TODO: complete device details
205 +// addLabels(node, device);
206 +// addProps(node, device);
207 +// addGeoLocation(node, device);
208 +// addMetaUi(node, device);
209 +
210 + return node;
211 + }
212 +
213 + private void addLabels(ObjectNode node, UiDevice device) {
214 +
215 + }
216 +
217 + private ObjectNode json(UiHost host) {
218 + return objectNode()
219 + .put("id", host.id().toString())
220 + .put("layer", host.layer());
221 + // TODO: complete host details
222 + }
223 +
224 +
225 + private ObjectNode json(UiLink link) {
226 + return objectNode()
227 + .put("id", link.id().toString());
228 + // TODO: complete link details
229 + }
230 +
231 +
232 +}
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;
18 +
19 +import com.fasterxml.jackson.databind.node.ObjectNode;
20 +import com.google.common.collect.ImmutableSet;
21 +import org.onlab.osgi.ServiceDirectory;
22 +import org.onosproject.ui.RequestHandler;
23 +import org.onosproject.ui.UiConnection;
24 +import org.onosproject.ui.UiMessageHandler;
25 +import org.onosproject.ui.impl.UiWebSocket;
26 +import org.onosproject.ui.model.topo.UiClusterMember;
27 +import org.onosproject.ui.model.topo.UiRegion;
28 +import org.onosproject.ui.model.topo.UiTopoLayout;
29 +import org.slf4j.Logger;
30 +import org.slf4j.LoggerFactory;
31 +
32 +import java.util.Collection;
33 +import java.util.List;
34 +
35 +/*
36 + NOTES:
37 +
38 + The original topology view message handler was broken into two classes
39 + TopologyViewMessageHandler, and TopologyViewMessageHandlerBase.
40 + We do not need to follow that model necessarily. Starting with a
41 + single class, and breaking it apart later if necessary.
42 +
43 + Need to figure out the connection between this message handler and the
44 + new way of doing things with UiTopoSession...
45 +
46 + */
47 +
48 +/**
49 + * Server-side component for interacting with the new "Region aware" topology
50 + * view in the Web UI.
51 + */
52 +public class Topo2ViewMessageHandler extends UiMessageHandler {
53 +
54 + private final Logger log = LoggerFactory.getLogger(getClass());
55 +
56 + // === Inbound event identifiers
57 + private static final String TOPO2_START = "topo2Start";
58 + private static final String TOPO2_STOP = "topo2Stop";
59 +
60 + // === Outbound event identifiers
61 + private static final String CURRENT_LAYOUT = "topo2CurrentLayout";
62 + private static final String CURRENT_REGION = "topo2CurrentRegion";
63 + private static final String ALL_INSTANCES = "topo2AllInstances";
64 + private static final String TOPO_START_DONE = "topo2StartDone";
65 +
66 + private UiTopoSession topoSession;
67 + private Topo2Jsonifier t2json;
68 +
69 +
70 + @Override
71 + public void init(UiConnection connection, ServiceDirectory directory) {
72 + super.init(connection, directory);
73 +
74 + // get the topo session from the UiWebSocket
75 + topoSession = ((UiWebSocket) connection).topoSession();
76 + t2json = new Topo2Jsonifier(directory);
77 + }
78 +
79 + @Override
80 + protected Collection<RequestHandler> createRequestHandlers() {
81 + return ImmutableSet.of(
82 + new Topo2Start(),
83 + new Topo2Stop()
84 + );
85 + }
86 +
87 + // ==================================================================
88 +
89 +
90 + private final class Topo2Start extends RequestHandler {
91 + private Topo2Start() {
92 + super(TOPO2_START);
93 + }
94 +
95 + @Override
96 + public void process(long sid, ObjectNode payload) {
97 + // client view is ready to receive data to display; so start up
98 + // server-side processing, and send over initial state
99 +
100 + log.debug("topo2Start: {}", payload);
101 +
102 + List<UiClusterMember> instances = topoSession.getAllInstances();
103 + sendMessage(ALL_INSTANCES, t2json.instances(instances));
104 +
105 + UiTopoLayout currentLayout = topoSession.currentLayout();
106 + sendMessage(CURRENT_LAYOUT, t2json.layout(currentLayout));
107 +
108 + UiRegion region = topoSession.getRegion(currentLayout);
109 + sendMessage(CURRENT_REGION, t2json.region(region));
110 +
111 + // TODO: send information about devices/hosts/links in non-region
112 + // TODO: send information about "linked, peer" regions
113 +
114 + sendMessage(TOPO_START_DONE, null);
115 +
116 +
117 + // OLD CODE DID THE FOLLOWING...
118 +// addListeners();
119 +// sendAllInstances(null);
120 +// sendAllDevices();
121 +// sendAllLinks();
122 +// sendAllHosts();
123 +// sendTopoStartDone();
124 + }
125 + }
126 +
127 + private final class Topo2Stop extends RequestHandler {
128 + private Topo2Stop() {
129 + super(TOPO2_STOP);
130 + }
131 +
132 + @Override
133 + public void process(long sid, ObjectNode payload) {
134 + // client view has gone away; so shut down server-side processing
135 + // TODO: implement...
136 +
137 + log.debug("topo2Stop: {}", payload);
138 +
139 + // OLD CODE DID THE FOLLOWING...
140 +// removeListeners();
141 +// stopSummaryMonitoring();
142 +// traffic.stopMonitoring();
143 + }
144 + }
145 +
146 +}
...@@ -21,10 +21,14 @@ import org.onosproject.ui.impl.UiWebSocket; ...@@ -21,10 +21,14 @@ import org.onosproject.ui.impl.UiWebSocket;
21 import org.onosproject.ui.impl.topo.model.UiModelEvent; 21 import org.onosproject.ui.impl.topo.model.UiModelEvent;
22 import org.onosproject.ui.impl.topo.model.UiModelListener; 22 import org.onosproject.ui.impl.topo.model.UiModelListener;
23 import org.onosproject.ui.impl.topo.model.UiSharedTopologyModel; 23 import org.onosproject.ui.impl.topo.model.UiSharedTopologyModel;
24 +import org.onosproject.ui.model.topo.UiClusterMember;
25 +import org.onosproject.ui.model.topo.UiRegion;
24 import org.onosproject.ui.model.topo.UiTopoLayout; 26 import org.onosproject.ui.model.topo.UiTopoLayout;
25 import org.slf4j.Logger; 27 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory; 28 import org.slf4j.LoggerFactory;
27 29
30 +import java.util.List;
31 +
28 /** 32 /**
29 * Coordinates with the {@link UiTopoLayoutService} to access 33 * Coordinates with the {@link UiTopoLayoutService} to access
30 * {@link UiTopoLayout}s, and with the {@link UiSharedTopologyModel} which 34 * {@link UiTopoLayout}s, and with the {@link UiSharedTopologyModel} which
...@@ -34,6 +38,10 @@ import org.slf4j.LoggerFactory; ...@@ -34,6 +38,10 @@ import org.slf4j.LoggerFactory;
34 * Note that an instance of this class will be created for each 38 * Note that an instance of this class will be created for each
35 * {@link UiWebSocket} connection, and will contain 39 * {@link UiWebSocket} connection, and will contain
36 * the state of how the topology is laid out for the logged-in user. 40 * the state of how the topology is laid out for the logged-in user.
41 + * <p>
42 + * The expected pattern is for the {@link Topo2ViewMessageHandler} to obtain
43 + * a reference to the session instance (via the {@link UiWebSocket}), and
44 + * interact with it when topo-related events come in from the client.
37 */ 45 */
38 public class UiTopoSession implements UiModelListener { 46 public class UiTopoSession implements UiModelListener {
39 private final Logger log = LoggerFactory.getLogger(getClass()); 47 private final Logger log = LoggerFactory.getLogger(getClass());
...@@ -129,4 +137,23 @@ public class UiTopoSession implements UiModelListener { ...@@ -129,4 +137,23 @@ public class UiTopoSession implements UiModelListener {
129 public void enableEvent(boolean enabled) { 137 public void enableEvent(boolean enabled) {
130 messagesEnabled = enabled; 138 messagesEnabled = enabled;
131 } 139 }
140 +
141 + /**
142 + * Returns the list of ONOS instances (cluster members).
143 + *
144 + * @return the list of ONOS instances
145 + */
146 + public List<UiClusterMember> getAllInstances() {
147 + return sharedModel.getClusterMembers();
148 + }
149 +
150 + /**
151 + * Returns the region for the specified layout.
152 + *
153 + * @param layout layout filter
154 + * @return region that the layout is based upon
155 + */
156 + public UiRegion getRegion(UiTopoLayout layout) {
157 + return sharedModel.getRegion(layout);
158 + }
132 } 159 }
......
...@@ -41,6 +41,7 @@ import org.onosproject.ui.model.topo.UiTopology; ...@@ -41,6 +41,7 @@ import org.onosproject.ui.model.topo.UiTopology;
41 import org.slf4j.Logger; 41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory; 42 import org.slf4j.LoggerFactory;
43 43
44 +import java.util.List;
44 import java.util.Set; 45 import java.util.Set;
45 46
46 import static org.onosproject.net.DefaultEdgeLink.createEdgeLink; 47 import static org.onosproject.net.DefaultEdgeLink.createEdgeLink;
...@@ -153,6 +154,10 @@ class ModelCache { ...@@ -153,6 +154,10 @@ class ModelCache {
153 } 154 }
154 } 155 }
155 156
157 + List<UiClusterMember> getAllClusterMembers() {
158 + return uiTopology.allClusterMembers();
159 + }
160 +
156 161
157 // === MASTERSHIP CHANGES 162 // === MASTERSHIP CHANGES
158 163
...@@ -199,7 +204,7 @@ class ModelCache { ...@@ -199,7 +204,7 @@ class ModelCache {
199 204
200 // package private for unit test access 205 // package private for unit test access
201 UiRegion accessRegion(RegionId id) { 206 UiRegion accessRegion(RegionId id) {
202 - return uiTopology.findRegion(id); 207 + return id == null ? null : uiTopology.findRegion(id);
203 } 208 }
204 209
205 // invoked from UiSharedTopologyModel region listener 210 // invoked from UiSharedTopologyModel region listener
...@@ -484,4 +489,5 @@ class ModelCache { ...@@ -484,4 +489,5 @@ class ModelCache {
484 public int hostCount() { 489 public int hostCount() {
485 return uiTopology.hostCount(); 490 return uiTopology.hostCount();
486 } 491 }
492 +
487 } 493 }
......
...@@ -16,9 +16,6 @@ ...@@ -16,9 +16,6 @@
16 16
17 package org.onosproject.ui.impl.topo.model; 17 package org.onosproject.ui.impl.topo.model;
18 18
19 -import java.util.concurrent.ExecutorService;
20 -import java.util.concurrent.Executors;
21 -
22 import org.apache.felix.scr.annotations.Activate; 19 import org.apache.felix.scr.annotations.Activate;
23 import org.apache.felix.scr.annotations.Component; 20 import org.apache.felix.scr.annotations.Component;
24 import org.apache.felix.scr.annotations.Deactivate; 21 import org.apache.felix.scr.annotations.Deactivate;
...@@ -64,9 +61,19 @@ import org.onosproject.net.statistic.StatisticService; ...@@ -64,9 +61,19 @@ import org.onosproject.net.statistic.StatisticService;
64 import org.onosproject.net.topology.TopologyService; 61 import org.onosproject.net.topology.TopologyService;
65 import org.onosproject.ui.impl.topo.UiTopoSession; 62 import org.onosproject.ui.impl.topo.UiTopoSession;
66 import org.onosproject.ui.model.ServiceBundle; 63 import org.onosproject.ui.model.ServiceBundle;
64 +import org.onosproject.ui.model.topo.UiClusterMember;
65 +import org.onosproject.ui.model.topo.UiElement;
66 +import org.onosproject.ui.model.topo.UiRegion;
67 +import org.onosproject.ui.model.topo.UiTopoLayout;
67 import org.slf4j.Logger; 68 import org.slf4j.Logger;
68 import org.slf4j.LoggerFactory; 69 import org.slf4j.LoggerFactory;
69 70
71 +import java.util.HashSet;
72 +import java.util.List;
73 +import java.util.Set;
74 +import java.util.concurrent.ExecutorService;
75 +import java.util.concurrent.Executors;
76 +
70 /** 77 /**
71 * Service that creates and maintains the UI-model of the network topology. 78 * Service that creates and maintains the UI-model of the network topology.
72 */ 79 */
...@@ -190,6 +197,41 @@ public final class UiSharedTopologyModel ...@@ -190,6 +197,41 @@ public final class UiSharedTopologyModel
190 removeListener(session); 197 removeListener(session);
191 } 198 }
192 199
200 +
201 + // =======================================================================
202 + // methods that the topo session will use to extract information from us
203 +
204 + /**
205 + * Returns the list of cluster members stored in our model cache.
206 + *
207 + * @return list of cluster members
208 + */
209 + public List<UiClusterMember> getClusterMembers() {
210 + return cache.getAllClusterMembers();
211 + }
212 +
213 + public Set<UiElement> getElements(UiTopoLayout layout) {
214 + Set<UiElement> results = new HashSet<>();
215 +
216 + // TODO: figure out how to extract the appropriate nodes
217 + // from the cache, for the given layout.
218 +
219 + return results;
220 + }
221 +
222 + /**
223 + * Returns the region for the given layout.
224 + *
225 + * @param layout layout filter
226 + * @return the region the layout is based upon
227 + */
228 + public UiRegion getRegion(UiTopoLayout layout) {
229 + return cache.accessRegion(layout.regionId());
230 + }
231 +
232 + // =====================================================================
233 +
234 +
193 /** 235 /**
194 * Default implementation of service bundle to return references to our 236 * Default implementation of service bundle to return references to our
195 * dynamically injected services. 237 * dynamically injected services.
......
...@@ -256,6 +256,8 @@ ...@@ -256,6 +256,8 @@
256 }); 256 });
257 } 257 }
258 258
259 + // TODO: simplify listener handling (see theme.js for sample code)
260 +
259 function addOpenListener(callback) { 261 function addOpenListener(callback) {
260 var id = nextListenerId++, 262 var id = nextListenerId++,
261 cb = fs.isF(callback), 263 cb = fs.isF(callback),
......
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 +
18 +/*
19 + ONOS GUI -- Topology View (theme) -- CSS file
20 + */
21 +
22 +/* --- Base SVG Layer --- */
23 +
24 +#ov-topo2 svg {
25 + /*background-color: #f4f4f4;*/
26 + background-color: goldenrod; /* just for testing */
27 +}
28 +
29 +/* --- "No Devices" Layer --- */
30 +
31 +#ov-topo2 svg .noDevsBird {
32 + fill: #db7773;
33 +}
34 +
35 +#ov-topo2 svg #topo2-noDevsLayer text {
36 + fill: #7e9aa8;
37 +}
38 +
39 +/* --- Topo Map --- */
40 +
41 +#ov-topo2 svg #topo2-map {
42 + stroke-width: 2px;
43 + stroke: #f4f4f4;
44 + fill: #e5e5e6;
45 +}
46 +
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 +
18 +/*
19 + ONOS GUI -- Topology View (layout) -- CSS file
20 + */
21 +
22 +/* --- Base SVG Layer --- */
23 +
24 +#ov-topo2 svg {
25 + /* prevents the little cut/copy/paste square that would appear on iPad */
26 + -webkit-user-select: none;
27 +}
1 +<!-- Topology View partial HTML -->
2 +<div id="ov-topo2">
3 + <svg viewBox="0 0 1000 1000"
4 + resize offset-height="56" offset-width="12"
5 + notifier="notifyResize()">
6 + </svg>
7 +</div>
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 +/*
18 + ONOS GUI -- Topology View Module
19 +
20 + NOTE: currently under development to support Regions.
21 + */
22 +
23 +(function () {
24 + 'use strict';
25 +
26 + // references to injected services
27 + var $scope, $log, $loc,
28 + fs, mast, ks, zs,
29 + gs, ms, sus, flash,
30 + wss, ps, th,
31 + t2es, t2fs;
32 +
33 + // DOM elements
34 + var ovtopo2, svg, defs, zoomLayer, mapG, spriteG, forceG, noDevsLayer;
35 +
36 + // Internal state
37 + var zoomer, actionMap;
38 +
39 +
40 + // === Helper Functions
41 +
42 + // callback invoked when the SVG view has been resized..
43 + function svgResized(s) {
44 + $log.debug("topo2 view resized", s);
45 + }
46 +
47 + function setUpKeys(overlayKeys) {
48 + $log.debug('topo2: set up keys....');
49 + }
50 +
51 + // === Controller Definition -----------------------------------------
52 +
53 + angular.module('ovTopo2', ['onosUtil', 'onosSvg', 'onosRemote'])
54 + .controller('OvTopo2Ctrl',
55 + ['$scope', '$log', '$location',
56 + 'FnService', 'MastService', 'KeyService', 'ZoomService',
57 + 'GlyphService', 'MapService', 'SvgUtilService', 'FlashService',
58 + 'WebSocketService', 'PrefsService', 'ThemeService',
59 + 'Topo2EventService', 'Topo2ForceService',
60 +
61 + function (_$scope_, _$log_, _$loc_,
62 + _fs_, _mast_, _ks_, _zs_,
63 + _gs_, _ms_, _sus_, _flash_,
64 + _wss_, _ps_, _th_,
65 + _t2es_, _t2fs_) {
66 +
67 + var params = _$loc_.search(),
68 + projection,
69 + dim,
70 + wh,
71 + uplink = {
72 + // provides function calls back into this space
73 + // showNoDevs: showNoDevs,
74 + // projection: function () { return projection; },
75 + // zoomLayer: function () { return zoomLayer; },
76 + // zoomer: function () { return zoomer; },
77 + // opacifyMap: opacifyMap,
78 + // topoStartDone: topoStartDone
79 + };
80 +
81 + $scope = _$scope_;
82 + $log = _$log_;
83 + $loc = _$loc_;
84 +
85 + fs = _fs_;
86 + mast = _mast_;
87 + ks = _ks_;
88 + zs = _zs_;
89 +
90 + gs = _gs_;
91 + ms = _ms_;
92 + sus = _sus_;
93 + flash = _flash_;
94 +
95 + wss = _wss_;
96 + ps = _ps_;
97 + th = _th_;
98 +
99 + t2es = _t2es_;
100 + t2fs = _t2fs_;
101 +
102 + // capture selected intent parameters (if they are set in the
103 + // query string) so that the traffic overlay can highlight
104 + // the path for that intent
105 + if (params.intentKey && params.intentAppId && params.intentAppName) {
106 + $scope.intentData = {
107 + key: params.intentKey,
108 + appId: params.intentAppId,
109 + appName: params.intentAppName
110 + };
111 + }
112 +
113 + $scope.notifyResize = function () {
114 + svgResized(fs.windowSize(mast.mastHeight()));
115 + };
116 +
117 + // Cleanup on destroyed scope..
118 + $scope.$on('$destroy', function () {
119 + $log.log('OvTopo2Ctrl is saying Buh-Bye!');
120 + t2es.stop();
121 + ks.unbindKeys();
122 + t2fs.destroy();
123 + });
124 +
125 + // svg layer and initialization of components
126 + ovtopo2 = d3.select('#ov-topo2');
127 + svg = ovtopo2.select('svg');
128 + // set the svg size to match that of the window, less the masthead
129 + wh = fs.windowSize(mast.mastHeight());
130 + $log.debug('setting topo SVG size to', wh);
131 + svg.attr(wh);
132 + dim = [wh.width, wh.height];
133 +
134 +
135 + // set up our keyboard shortcut bindings
136 + setUpKeys();
137 +
138 + // make sure we can respond to topology events from the server
139 + t2es.bindHandlers();
140 +
141 + // initialize the force layout, ready to render the topology
142 + t2fs.init();
143 +
144 +
145 + // =-=-=-=-=-=-=-=-
146 + // TODO: in future, we will load background map data
147 + // asynchronously (hence the promise) and then chain off
148 + // there to send the topo2start event to the server.
149 + // For now, we'll send the event inline...
150 + t2es.start();
151 +
152 +
153 + // === ORIGINAL CODE ===
154 +
155 + // setUpKeys();
156 + // setUpToolbar();
157 + // setUpDefs();
158 + // setUpZoom();
159 + // setUpNoDevs();
160 + /*
161 + setUpMap().then(
162 + function (proj) {
163 + var z = ps.getPrefs('topo_zoom', { tx:0, ty:0, sc:1 });
164 + zoomer.panZoom([z.tx, z.ty], z.sc);
165 + $log.debug('** Zoom restored:', z);
166 +
167 + projection = proj;
168 + $log.debug('** We installed the projection:', proj);
169 + flash.enable(false);
170 + toggleMap(prefsState.bg);
171 + flash.enable(true);
172 + mapShader(true);
173 +
174 + // now we have the map projection, we are ready for
175 + // the server to send us device/host data...
176 + tes.start();
177 + // need to do the following so we immediately get
178 + // the summary panel data back from the server
179 + restoreSummaryFromPrefs();
180 + }
181 + );
182 + */
183 + // tes.bindHandlers();
184 + // setUpSprites();
185 +
186 + // forceG = zoomLayer.append('g').attr('id', 'topo-force');
187 + // tfs.initForce(svg, forceG, uplink, dim);
188 + // tis.initInst({ showMastership: tfs.showMastership });
189 + // tps.initPanels();
190 +
191 + // restoreConfigFromPrefs();
192 + // ttbs.setDefaultOverlay(prefsState.ovidx);
193 +
194 + // $log.debug('registered overlays...', tov.list());
195 +
196 + $log.log('OvTopo2Ctrl has been created');
197 + }]);
198 +}());
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 +/*
18 + ONOS GUI -- Topology Event Module.
19 +
20 + Defines the conduit between the client and the server:
21 + - provides a clean API for sending events to the server
22 + - dispatches incoming events from the server to the appropriate sub-module
23 +
24 + */
25 +
26 +(function () {
27 + 'use strict';
28 +
29 + // injected refs
30 + var $log, wss, t2fs;
31 +
32 + // internal state
33 + var handlerMap,
34 + openListener;
35 +
36 + // TODO: only add heartbeat timer etc. if we really need to be doing that..
37 +
38 + // ========================== Helper Functions
39 +
40 + function createHandlerMap() {
41 + handlerMap = {
42 + topo2AllInstances: t2fs,
43 + topo2CurrentLayout: t2fs,
44 + topo2CurrentRegion: t2fs,
45 + topo2StartDone: t2fs
46 +
47 + // Add further event names / module references as needed
48 + };
49 + }
50 +
51 + function wsOpen(host, url) {
52 + $log.debug('topo2Event: WSopen - cluster node:', host, 'URL:', url);
53 + // tell the server we are ready to receive topo events
54 + wss.sendEvent('topo2Start');
55 + }
56 +
57 + // bind our event handlers to the web socket service, so that our
58 + // callbacks get invoked for incoming events
59 + function bindHandlers() {
60 + wss.bindHandlers(handlerMap);
61 + $log.debug('topo2 event handlers bound');
62 + }
63 +
64 + // tell the server we are ready to receive topology events
65 + function start() {
66 + // in case we fail over to a new server,
67 + // listen for wsock-open events
68 + openListener = wss.addOpenListener(wsOpen);
69 + wss.sendEvent('topo2Start');
70 + $log.debug('topo2 comms started');
71 + }
72 +
73 + // tell the server we no longer wish to receive topology events
74 + function stop() {
75 + wss.sendEvent('topo2Stop');
76 + wss.unbindHandlers(handlerMap);
77 + wss.removeOpenListener(openListener);
78 + openListener = null;
79 + $log.debug('topo2 comms stopped');
80 + }
81 +
82 + // ========================== Main Service Definition
83 +
84 + angular.module('ovTopo2')
85 + .factory('Topo2EventService',
86 + ['$log', 'WebSocketService', 'Topo2ForceService',
87 +
88 + function (_$log_, _wss_, _t2fs_) {
89 + $log = _$log_;
90 + wss = _wss_;
91 + t2fs = _t2fs_;
92 +
93 + // deferred creation of handler map, so module references are good
94 + createHandlerMap();
95 +
96 + return {
97 + bindHandlers: bindHandlers,
98 + start: start,
99 + stop: stop
100 + };
101 + }]);
102 +}());
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 +/*
18 + ONOS GUI -- Topology Force Module.
19 + Visualization of the topology in an SVG layer, using a D3 Force Layout.
20 + */
21 +
22 +(function () {
23 + 'use strict';
24 +
25 + // injected refs
26 + var $log, wss;
27 +
28 + // ========================== Helper Functions
29 +
30 + function init() {
31 + $log.debug('Initialize topo force layout');
32 + }
33 +
34 + function destroy() {
35 + $log.debug('Destroy topo force layout');
36 + }
37 +
38 + // ========================== Event Handlers
39 +
40 + function allInstances(data) {
41 + $log.debug('>> topo2AllInstances event:', data)
42 + }
43 +
44 + function currentLayout(data) {
45 + $log.debug('>> topo2CurrentLayout event:', data)
46 + }
47 +
48 + function currentRegion(data) {
49 + $log.debug('>> topo2CurrentRegion event:', data)
50 + }
51 +
52 + function startDone(data) {
53 + $log.debug('>> topo2StartDone event:', data)
54 + }
55 +
56 + // ========================== Main Service Definition
57 +
58 + angular.module('ovTopo2')
59 + .factory('Topo2ForceService',
60 + ['$log', 'WebSocketService',
61 +
62 + function (_$log_, _wss_) {
63 + $log = _$log_;
64 + wss = _wss_;
65 +
66 + return {
67 + init: init,
68 + destroy: destroy,
69 + topo2AllInstances: allInstances,
70 + topo2CurrentLayout: currentLayout,
71 + topo2CurrentRegion: currentRegion,
72 + topo2StartDone: startDone
73 + };
74 + }]);
75 +}());
...@@ -126,6 +126,13 @@ ...@@ -126,6 +126,13 @@
126 <link rel="stylesheet" href="app/fw/widget/table.css"> 126 <link rel="stylesheet" href="app/fw/widget/table.css">
127 <link rel="stylesheet" href="app/fw/widget/table-theme.css"> 127 <link rel="stylesheet" href="app/fw/widget/table-theme.css">
128 128
129 + <!-- Under development for Region support. -->
130 + <script src="app/view/topo2/topo2.js"></script>
131 + <script src="app/view/topo2/topo2Event.js"></script>
132 + <script src="app/view/topo2/topo2Force.js"></script>
133 + <link rel="stylesheet" href="app/view/topo2/topo2.css">
134 + <link rel="stylesheet" href="app/view/topo2/topo2-theme.css">
135 +
129 <!-- Builtin views javascript. --> 136 <!-- Builtin views javascript. -->
130 <script src="app/view/topo/topo.js"></script> 137 <script src="app/view/topo/topo.js"></script>
131 <script src="app/view/topo/topoD3.js"></script> 138 <script src="app/view/topo/topoD3.js"></script>
......