ONOS-4971: Synthetic Link Data -- WIP, merge anyway
- created temp Topology2 View (topoX) to "process" and display topology data. - made root layout parent of itself (just like /.. = /) to simplify layout hierarchy operations. - added nodeType property to JSON rep of regions/devices/hosts. - augmented peers to include devices. - added skeleton topo2NavRegion event. Change-Id: I8219125d7dfe33d211350ae27111a3d9de6eb4ca
Showing
19 changed files
with
869 additions
and
21 deletions
| ... | @@ -63,7 +63,7 @@ public interface UiTopoLayoutService { | ... | @@ -63,7 +63,7 @@ public interface UiTopoLayoutService { |
| 63 | * @param layoutId layout identifier | 63 | * @param layoutId layout identifier |
| 64 | * @return set of peer layouts; empty set if layout has no peers | 64 | * @return set of peer layouts; empty set if layout has no peers |
| 65 | */ | 65 | */ |
| 66 | - Set<UiTopoLayout> getPeers(UiTopoLayoutId layoutId); | 66 | + Set<UiTopoLayout> getPeerLayouts(UiTopoLayoutId layoutId); |
| 67 | 67 | ||
| 68 | /** | 68 | /** |
| 69 | * Returns the set of the child layouts of the specified layout. | 69 | * Returns the set of the child layouts of the specified layout. | ... | ... |
| ... | @@ -39,7 +39,8 @@ public class UiTopoLayout { | ... | @@ -39,7 +39,8 @@ public class UiTopoLayout { |
| 39 | public UiTopoLayout(UiTopoLayoutId id, Region region, UiTopoLayoutId parent) { | 39 | public UiTopoLayout(UiTopoLayoutId id, Region region, UiTopoLayoutId parent) { |
| 40 | this.id = id; | 40 | this.id = id; |
| 41 | this.region = region; | 41 | this.region = region; |
| 42 | - this.parent = parent; | 42 | + // NOTE: root layout is its own parent... |
| 43 | + this.parent = parent != null ? parent : this.id; | ||
| 43 | } | 44 | } |
| 44 | 45 | ||
| 45 | @Override | 46 | @Override |
| ... | @@ -85,5 +86,13 @@ public class UiTopoLayout { | ... | @@ -85,5 +86,13 @@ public class UiTopoLayout { |
| 85 | return parent; | 86 | return parent; |
| 86 | } | 87 | } |
| 87 | 88 | ||
| 88 | - // TODO: additional properties pertinent to the layout | 89 | + /** |
| 90 | + * Returns true if this layout instance is at the top of the | ||
| 91 | + * hierarchy tree. | ||
| 92 | + * | ||
| 93 | + * @return true if this is the root layout | ||
| 94 | + */ | ||
| 95 | + public boolean isRoot() { | ||
| 96 | + return id.equals(parent); | ||
| 97 | + } | ||
| 89 | } | 98 | } | ... | ... |
| ... | @@ -134,6 +134,7 @@ public class UiExtensionManager | ... | @@ -134,6 +134,7 @@ public class UiExtensionManager |
| 134 | 134 | ||
| 135 | // FIXME: leave commented out for now, while still under development | 135 | // FIXME: leave commented out for now, while still under development |
| 136 | // new UiView(NETWORK, "topo2", "New-Topo"), | 136 | // new UiView(NETWORK, "topo2", "New-Topo"), |
| 137 | +// new UiView(NETWORK, "topoX", "Topo-X"), | ||
| 137 | 138 | ||
| 138 | new UiView(NETWORK, "device", "Devices", "nav_devs"), | 139 | new UiView(NETWORK, "device", "Devices", "nav_devs"), |
| 139 | new UiViewHidden("flow"), | 140 | new UiViewHidden("flow"), | ... | ... |
| ... | @@ -40,6 +40,8 @@ import org.onosproject.ui.model.topo.UiLink; | ... | @@ -40,6 +40,8 @@ import org.onosproject.ui.model.topo.UiLink; |
| 40 | import org.onosproject.ui.model.topo.UiNode; | 40 | import org.onosproject.ui.model.topo.UiNode; |
| 41 | import org.onosproject.ui.model.topo.UiRegion; | 41 | import org.onosproject.ui.model.topo.UiRegion; |
| 42 | import org.onosproject.ui.model.topo.UiTopoLayout; | 42 | import org.onosproject.ui.model.topo.UiTopoLayout; |
| 43 | +import org.slf4j.Logger; | ||
| 44 | +import org.slf4j.LoggerFactory; | ||
| 43 | 45 | ||
| 44 | import java.util.ArrayList; | 46 | import java.util.ArrayList; |
| 45 | import java.util.HashMap; | 47 | import java.util.HashMap; |
| ... | @@ -62,6 +64,12 @@ class Topo2Jsonifier { | ... | @@ -62,6 +64,12 @@ class Topo2Jsonifier { |
| 62 | private static final String E_UNKNOWN_UI_NODE = | 64 | private static final String E_UNKNOWN_UI_NODE = |
| 63 | "Unknown subclass of UiNode: "; | 65 | "Unknown subclass of UiNode: "; |
| 64 | 66 | ||
| 67 | + private static final String REGION = "region"; | ||
| 68 | + private static final String DEVICE = "device"; | ||
| 69 | + private static final String HOST = "host"; | ||
| 70 | + | ||
| 71 | + private final Logger log = LoggerFactory.getLogger(getClass()); | ||
| 72 | + | ||
| 65 | private final ObjectMapper mapper = new ObjectMapper(); | 73 | private final ObjectMapper mapper = new ObjectMapper(); |
| 66 | 74 | ||
| 67 | private ServiceDirectory directory; | 75 | private ServiceDirectory directory; |
| ... | @@ -245,6 +253,7 @@ class Topo2Jsonifier { | ... | @@ -245,6 +253,7 @@ class Topo2Jsonifier { |
| 245 | private ObjectNode json(UiDevice device) { | 253 | private ObjectNode json(UiDevice device) { |
| 246 | ObjectNode node = objectNode() | 254 | ObjectNode node = objectNode() |
| 247 | .put("id", device.idAsString()) | 255 | .put("id", device.idAsString()) |
| 256 | + .put("nodeType", DEVICE) | ||
| 248 | .put("type", device.type()) | 257 | .put("type", device.type()) |
| 249 | .put("online", device.isOnline()) | 258 | .put("online", device.isOnline()) |
| 250 | .put("master", nullIsEmpty(device.master())) | 259 | .put("master", nullIsEmpty(device.master())) |
| ... | @@ -266,6 +275,7 @@ class Topo2Jsonifier { | ... | @@ -266,6 +275,7 @@ class Topo2Jsonifier { |
| 266 | private ObjectNode json(UiHost host) { | 275 | private ObjectNode json(UiHost host) { |
| 267 | return objectNode() | 276 | return objectNode() |
| 268 | .put("id", host.idAsString()) | 277 | .put("id", host.idAsString()) |
| 278 | + .put("nodeType", HOST) | ||
| 269 | .put("layer", host.layer()); | 279 | .put("layer", host.layer()); |
| 270 | // TODO: complete host details | 280 | // TODO: complete host details |
| 271 | } | 281 | } |
| ... | @@ -281,10 +291,31 @@ class Topo2Jsonifier { | ... | @@ -281,10 +291,31 @@ class Topo2Jsonifier { |
| 281 | private ObjectNode jsonClosedRegion(UiRegion region) { | 291 | private ObjectNode jsonClosedRegion(UiRegion region) { |
| 282 | return objectNode() | 292 | return objectNode() |
| 283 | .put("id", region.idAsString()) | 293 | .put("id", region.idAsString()) |
| 294 | + .put("nodeType", REGION) | ||
| 284 | .put("nDevs", region.deviceCount()); | 295 | .put("nDevs", region.deviceCount()); |
| 285 | // TODO: complete closed-region details | 296 | // TODO: complete closed-region details |
| 286 | } | 297 | } |
| 287 | 298 | ||
| 299 | + /** | ||
| 300 | + * Returns a JSON array representation of a set of regions/devices. Note | ||
| 301 | + * that the information is sufficient for showing regions as nodes. | ||
| 302 | + * | ||
| 303 | + * @param nodes the nodes | ||
| 304 | + * @return a JSON representation of the nodes | ||
| 305 | + */ | ||
| 306 | + public ArrayNode closedNodes(Set<UiNode> nodes) { | ||
| 307 | + ArrayNode array = arrayNode(); | ||
| 308 | + for (UiNode node: nodes) { | ||
| 309 | + if (node instanceof UiRegion) { | ||
| 310 | + array.add(jsonClosedRegion((UiRegion) node)); | ||
| 311 | + } else if (node instanceof UiDevice) { | ||
| 312 | + array.add(json((UiDevice) node)); | ||
| 313 | + } else { | ||
| 314 | + log.warn("Unexpected node instance: {}", node.getClass()); | ||
| 315 | + } | ||
| 316 | + } | ||
| 317 | + return array; | ||
| 318 | + } | ||
| 288 | 319 | ||
| 289 | /** | 320 | /** |
| 290 | * Returns a JSON array representation of a list of regions. Note that the | 321 | * Returns a JSON array representation of a list of regions. Note that the | ... | ... |
| ... | @@ -24,6 +24,7 @@ import org.onosproject.ui.UiConnection; | ... | @@ -24,6 +24,7 @@ import org.onosproject.ui.UiConnection; |
| 24 | import org.onosproject.ui.UiMessageHandler; | 24 | import org.onosproject.ui.UiMessageHandler; |
| 25 | import org.onosproject.ui.impl.UiWebSocket; | 25 | import org.onosproject.ui.impl.UiWebSocket; |
| 26 | import org.onosproject.ui.model.topo.UiClusterMember; | 26 | import org.onosproject.ui.model.topo.UiClusterMember; |
| 27 | +import org.onosproject.ui.model.topo.UiNode; | ||
| 27 | import org.onosproject.ui.model.topo.UiRegion; | 28 | import org.onosproject.ui.model.topo.UiRegion; |
| 28 | import org.onosproject.ui.model.topo.UiTopoLayout; | 29 | import org.onosproject.ui.model.topo.UiTopoLayout; |
| 29 | import org.slf4j.Logger; | 30 | import org.slf4j.Logger; |
| ... | @@ -55,8 +56,9 @@ public class Topo2ViewMessageHandler extends UiMessageHandler { | ... | @@ -55,8 +56,9 @@ public class Topo2ViewMessageHandler extends UiMessageHandler { |
| 55 | private final Logger log = LoggerFactory.getLogger(getClass()); | 56 | private final Logger log = LoggerFactory.getLogger(getClass()); |
| 56 | 57 | ||
| 57 | // === Inbound event identifiers | 58 | // === Inbound event identifiers |
| 58 | - private static final String TOPO2_START = "topo2Start"; | 59 | + private static final String START = "topo2Start"; |
| 59 | - private static final String TOPO2_STOP = "topo2Stop"; | 60 | + private static final String NAV_REGION = "topo2navRegion"; |
| 61 | + private static final String STOP = "topo2Stop"; | ||
| 60 | 62 | ||
| 61 | // === Outbound event identifiers | 63 | // === Outbound event identifiers |
| 62 | private static final String ALL_INSTANCES = "topo2AllInstances"; | 64 | private static final String ALL_INSTANCES = "topo2AllInstances"; |
| ... | @@ -83,6 +85,7 @@ public class Topo2ViewMessageHandler extends UiMessageHandler { | ... | @@ -83,6 +85,7 @@ public class Topo2ViewMessageHandler extends UiMessageHandler { |
| 83 | protected Collection<RequestHandler> createRequestHandlers() { | 85 | protected Collection<RequestHandler> createRequestHandlers() { |
| 84 | return ImmutableSet.of( | 86 | return ImmutableSet.of( |
| 85 | new Topo2Start(), | 87 | new Topo2Start(), |
| 88 | + new Topo2NavRegion(), | ||
| 86 | new Topo2Stop() | 89 | new Topo2Stop() |
| 87 | ); | 90 | ); |
| 88 | } | 91 | } |
| ... | @@ -92,7 +95,7 @@ public class Topo2ViewMessageHandler extends UiMessageHandler { | ... | @@ -92,7 +95,7 @@ public class Topo2ViewMessageHandler extends UiMessageHandler { |
| 92 | 95 | ||
| 93 | private final class Topo2Start extends RequestHandler { | 96 | private final class Topo2Start extends RequestHandler { |
| 94 | private Topo2Start() { | 97 | private Topo2Start() { |
| 95 | - super(TOPO2_START); | 98 | + super(START); |
| 96 | } | 99 | } |
| 97 | 100 | ||
| 98 | @Override | 101 | @Override |
| ... | @@ -124,10 +127,10 @@ public class Topo2ViewMessageHandler extends UiMessageHandler { | ... | @@ -124,10 +127,10 @@ public class Topo2ViewMessageHandler extends UiMessageHandler { |
| 124 | Set<UiRegion> kids = topoSession.getSubRegions(currentLayout); | 127 | Set<UiRegion> kids = topoSession.getSubRegions(currentLayout); |
| 125 | sendMessage(CURRENT_REGION, t2json.region(region, kids)); | 128 | sendMessage(CURRENT_REGION, t2json.region(region, kids)); |
| 126 | 129 | ||
| 127 | - // these are the regions that are siblings to this one | 130 | + // these are the regions/devices that are siblings to this region |
| 128 | - Set<UiRegion> peers = topoSession.getPeerRegions(currentLayout); | 131 | + Set<UiNode> peers = topoSession.getPeerNodes(currentLayout); |
| 129 | ObjectNode peersPayload = objectNode(); | 132 | ObjectNode peersPayload = objectNode(); |
| 130 | - peersPayload.set("peers", t2json.closedRegions(peers)); | 133 | + peersPayload.set("peers", t2json.closedNodes(peers)); |
| 131 | sendMessage(PEER_REGIONS, peersPayload); | 134 | sendMessage(PEER_REGIONS, peersPayload); |
| 132 | 135 | ||
| 133 | // finally, tell the UI that we are done : TODO review / delete?? | 136 | // finally, tell the UI that we are done : TODO review / delete?? |
| ... | @@ -146,9 +149,22 @@ public class Topo2ViewMessageHandler extends UiMessageHandler { | ... | @@ -146,9 +149,22 @@ public class Topo2ViewMessageHandler extends UiMessageHandler { |
| 146 | 149 | ||
| 147 | } | 150 | } |
| 148 | 151 | ||
| 152 | + private final class Topo2NavRegion extends RequestHandler { | ||
| 153 | + private Topo2NavRegion() { | ||
| 154 | + super(NAV_REGION); | ||
| 155 | + } | ||
| 156 | + | ||
| 157 | + @Override | ||
| 158 | + public void process(long sid, ObjectNode payload) { | ||
| 159 | + String dir = string(payload, "dir"); | ||
| 160 | + String rid = string(payload, "rid"); | ||
| 161 | + log.debug("NavRegion: dir={}, rid={}", dir, rid); | ||
| 162 | + } | ||
| 163 | + } | ||
| 164 | + | ||
| 149 | private final class Topo2Stop extends RequestHandler { | 165 | private final class Topo2Stop extends RequestHandler { |
| 150 | private Topo2Stop() { | 166 | private Topo2Stop() { |
| 151 | - super(TOPO2_STOP); | 167 | + super(STOP); |
| 152 | } | 168 | } |
| 153 | 169 | ||
| 154 | @Override | 170 | @Override | ... | ... |
| ... | @@ -111,15 +111,17 @@ public class UiTopoLayoutManager implements UiTopoLayoutService { | ... | @@ -111,15 +111,17 @@ public class UiTopoLayoutManager implements UiTopoLayoutService { |
| 111 | } | 111 | } |
| 112 | 112 | ||
| 113 | @Override | 113 | @Override |
| 114 | - public Set<UiTopoLayout> getPeers(UiTopoLayoutId layoutId) { | 114 | + public Set<UiTopoLayout> getPeerLayouts(UiTopoLayoutId layoutId) { |
| 115 | checkNotNull(layoutId, ID_NULL); | 115 | checkNotNull(layoutId, ID_NULL); |
| 116 | + | ||
| 116 | UiTopoLayout layout = layoutMap.get(layoutId); | 117 | UiTopoLayout layout = layoutMap.get(layoutId); |
| 117 | - if (layout == null) { | 118 | + if (layout == null || layout.isRoot()) { |
| 118 | return Collections.emptySet(); | 119 | return Collections.emptySet(); |
| 119 | } | 120 | } |
| 120 | 121 | ||
| 121 | UiTopoLayoutId parentId = layout.parent(); | 122 | UiTopoLayoutId parentId = layout.parent(); |
| 122 | return layoutMap.values().stream() | 123 | return layoutMap.values().stream() |
| 124 | + // all layouts who are NOT me and who share my parent... | ||
| 123 | .filter(l -> !Objects.equals(l.id(), layoutId) && | 125 | .filter(l -> !Objects.equals(l.id(), layoutId) && |
| 124 | Objects.equals(l.parent(), parentId)) | 126 | Objects.equals(l.parent(), parentId)) |
| 125 | .collect(Collectors.toSet()); | 127 | .collect(Collectors.toSet()); |
| ... | @@ -129,7 +131,7 @@ public class UiTopoLayoutManager implements UiTopoLayoutService { | ... | @@ -129,7 +131,7 @@ public class UiTopoLayoutManager implements UiTopoLayoutService { |
| 129 | public Set<UiTopoLayout> getChildren(UiTopoLayoutId layoutId) { | 131 | public Set<UiTopoLayout> getChildren(UiTopoLayoutId layoutId) { |
| 130 | checkNotNull(layoutId, ID_NULL); | 132 | checkNotNull(layoutId, ID_NULL); |
| 131 | return layoutMap.values().stream() | 133 | return layoutMap.values().stream() |
| 132 | - .filter(l -> Objects.equals(l.parent(), layoutId)) | 134 | + .filter(l -> !l.isRoot() && Objects.equals(l.parent(), layoutId)) |
| 133 | .collect(Collectors.toSet()); | 135 | .collect(Collectors.toSet()); |
| 134 | } | 136 | } |
| 135 | 137 | ... | ... |
| ... | @@ -23,6 +23,7 @@ import org.onosproject.ui.impl.topo.model.UiModelEvent; | ... | @@ -23,6 +23,7 @@ import org.onosproject.ui.impl.topo.model.UiModelEvent; |
| 23 | import org.onosproject.ui.impl.topo.model.UiModelListener; | 23 | import org.onosproject.ui.impl.topo.model.UiModelListener; |
| 24 | import org.onosproject.ui.impl.topo.model.UiSharedTopologyModel; | 24 | import org.onosproject.ui.impl.topo.model.UiSharedTopologyModel; |
| 25 | import org.onosproject.ui.model.topo.UiClusterMember; | 25 | import org.onosproject.ui.model.topo.UiClusterMember; |
| 26 | +import org.onosproject.ui.model.topo.UiNode; | ||
| 26 | import org.onosproject.ui.model.topo.UiRegion; | 27 | import org.onosproject.ui.model.topo.UiRegion; |
| 27 | import org.onosproject.ui.model.topo.UiTopoLayout; | 28 | import org.onosproject.ui.model.topo.UiTopoLayout; |
| 28 | import org.slf4j.Logger; | 29 | import org.slf4j.Logger; |
| ... | @@ -170,17 +171,32 @@ public class UiTopoSession implements UiModelListener { | ... | @@ -170,17 +171,32 @@ public class UiTopoSession implements UiModelListener { |
| 170 | } | 171 | } |
| 171 | 172 | ||
| 172 | /** | 173 | /** |
| 173 | - * Returns the regions that are "peers" to this region. That is, based on | 174 | + * Returns the regions/devices that are "peers" to this region. That is, |
| 174 | - * the layout the user is viewing, all the regions that are associated with | 175 | + * based on the layout the user is viewing, all the regions/devices that |
| 175 | - * layouts that share the same parent layout as this layout. | 176 | + * are associated with layouts that share the same parent layout as this |
| 177 | + * layout, AND that are linked to an element within this region. | ||
| 176 | * | 178 | * |
| 177 | * @param layout the layout being viewed | 179 | * @param layout the layout being viewed |
| 178 | - * @return all regions that are "siblings" to this layout's region | 180 | + * @return all regions/devices that are "siblings" to this layout's region |
| 179 | */ | 181 | */ |
| 180 | - public Set<UiRegion> getPeerRegions(UiTopoLayout layout) { | 182 | + public Set<UiNode> getPeerNodes(UiTopoLayout layout) { |
| 181 | - Set<UiTopoLayout> peerLayouts = layoutService.getPeers(layout.id()); | 183 | + Set<UiNode> peers = new HashSet<>(); |
| 182 | - Set<UiRegion> peers = new HashSet<>(); | 184 | + |
| 183 | - peerLayouts.forEach(l -> peers.add(sharedModel.getRegion(l.regionId()))); | 185 | + // first, get the peer regions |
| 186 | + Set<UiTopoLayout> peerLayouts = layoutService.getPeerLayouts(layout.id()); | ||
| 187 | + peerLayouts.forEach(l -> { | ||
| 188 | + RegionId peerRegion = l.regionId(); | ||
| 189 | + peers.add(sharedModel.getRegion(peerRegion)); | ||
| 190 | + }); | ||
| 191 | + | ||
| 192 | + // now add the devices that reside in the parent region | ||
| 193 | + if (!layout.isRoot()) { | ||
| 194 | + UiTopoLayout parentLayout = layoutService.getLayout(layout.parent()); | ||
| 195 | + getRegion(parentLayout).devices().forEach(peers::add); | ||
| 196 | + } | ||
| 197 | + | ||
| 198 | + // TODO: Finally, filter out regions / devices that are not connected | ||
| 199 | + // directly to this region by an implicit link | ||
| 184 | return peers; | 200 | return peers; |
| 185 | } | 201 | } |
| 186 | 202 | ... | ... |
| ... | @@ -25,3 +25,28 @@ | ... | @@ -25,3 +25,28 @@ |
| 25 | /* prevents the little cut/copy/paste square that would appear on iPad */ | 25 | /* prevents the little cut/copy/paste square that would appear on iPad */ |
| 26 | -webkit-user-select: none; | 26 | -webkit-user-select: none; |
| 27 | } | 27 | } |
| 28 | + | ||
| 29 | +/* -- TEMPORARY CSS (to be deleted) -- */ | ||
| 30 | +#topo2tmp div { | ||
| 31 | + padding: 8px 24px; | ||
| 32 | + margin: 8px; | ||
| 33 | + background-color: #ddddff; | ||
| 34 | +} | ||
| 35 | +#topo2tmp div div { | ||
| 36 | + padding: 4px 10px; | ||
| 37 | +} | ||
| 38 | + | ||
| 39 | +#topo2tmp h4 { | ||
| 40 | + margin: 0 | ||
| 41 | +} | ||
| 42 | +#topo2tmp p { | ||
| 43 | + margin: 0 | ||
| 44 | +} | ||
| 45 | +#topo2tmp .nav-me:hover { | ||
| 46 | + background-color: #bbbbdd; | ||
| 47 | +} | ||
| 48 | +#topo2tmp .nav-me { | ||
| 49 | + font-weight: bold; | ||
| 50 | + text-decoration: underline; | ||
| 51 | + cursor: pointer; | ||
| 52 | +} | ... | ... |
| 1 | <!-- Topology View partial HTML --> | 1 | <!-- Topology View partial HTML --> |
| 2 | <div id="ov-topo2"> | 2 | <div id="ov-topo2"> |
| 3 | + <div id="topo2tmp"> | ||
| 4 | + <div class="parentRegion"> | ||
| 5 | + Parent Region: <span> - </span> | ||
| 6 | + </div> | ||
| 7 | + <div class="thisRegion"> | ||
| 8 | + This Region: <span> - </span> | ||
| 9 | + </div> | ||
| 10 | + <div class="subRegions"> | ||
| 11 | + <h4>Subregions</h4> | ||
| 12 | + <div></div> | ||
| 13 | + </div> | ||
| 14 | + <div class="devices"> | ||
| 15 | + <h4>Devices</h4> | ||
| 16 | + <div></div> | ||
| 17 | + </div> | ||
| 18 | + <div class="hosts"> | ||
| 19 | + <h4>Hosts</h4> | ||
| 20 | + <div></div> | ||
| 21 | + </div> | ||
| 22 | + <div class="links"> | ||
| 23 | + <h4>Links</h4> | ||
| 24 | + <div></div> | ||
| 25 | + </div> | ||
| 26 | + <div class="peers"> | ||
| 27 | + <h4>Peers</h4> | ||
| 28 | + <div></div> | ||
| 29 | + </div> | ||
| 30 | + </div> | ||
| 31 | + | ||
| 32 | + <!-- Below here is good; Above here is temporary, for debugging --> | ||
| 33 | + | ||
| 3 | <svg viewBox="0 0 1000 1000" | 34 | <svg viewBox="0 0 1000 1000" |
| 4 | resize offset-height="56" offset-width="12" | 35 | resize offset-height="56" offset-width="12" |
| 5 | notifier="notifyResize()"> | 36 | notifier="notifyResize()"> | ... | ... |
| ... | @@ -42,6 +42,7 @@ | ... | @@ -42,6 +42,7 @@ |
| 42 | topo2AllInstances: t2fs, | 42 | topo2AllInstances: t2fs, |
| 43 | topo2CurrentLayout: t2fs, | 43 | topo2CurrentLayout: t2fs, |
| 44 | topo2CurrentRegion: t2fs, | 44 | topo2CurrentRegion: t2fs, |
| 45 | + topo2PeerRegions: t2fs, | ||
| 45 | topo2StartDone: t2fs | 46 | topo2StartDone: t2fs |
| 46 | 47 | ||
| 47 | // Add further event names / module references as needed | 48 | // Add further event names / module references as needed | ... | ... |
| ... | @@ -35,10 +35,79 @@ | ... | @@ -35,10 +35,79 @@ |
| 35 | $log.debug('Destroy topo force layout'); | 35 | $log.debug('Destroy topo force layout'); |
| 36 | } | 36 | } |
| 37 | 37 | ||
| 38 | + // ========================== Temporary Code (to be deleted later) | ||
| 39 | + | ||
| 40 | + function request(dir, rid) { | ||
| 41 | + wss.sendEvent('topo2navRegion', { | ||
| 42 | + dir: dir, | ||
| 43 | + rid: rid | ||
| 44 | + }); | ||
| 45 | + } | ||
| 46 | + | ||
| 47 | + function doTmpCurrentLayout(data) { | ||
| 48 | + var topdiv = d3.select('#topo2tmp'); | ||
| 49 | + var parentRegion = data.parent; | ||
| 50 | + var span = topdiv.select('.parentRegion').select('span'); | ||
| 51 | + span.text(parentRegion || '[no parent]'); | ||
| 52 | + span.classed('nav-me', !!parentRegion); | ||
| 53 | + } | ||
| 54 | + | ||
| 55 | + function doTmpCurrentRegion(data) { | ||
| 56 | + var topdiv = d3.select('#topo2tmp'); | ||
| 57 | + var span = topdiv.select('.thisRegion').select('span'); | ||
| 58 | + var div; | ||
| 59 | + | ||
| 60 | + span.text(data.id); | ||
| 61 | + | ||
| 62 | + div = topdiv.select('.subRegions').select('div'); | ||
| 63 | + data.subregions.forEach(function (r) { | ||
| 64 | + | ||
| 65 | + function nav() { | ||
| 66 | + request('down', r.id); | ||
| 67 | + } | ||
| 68 | + | ||
| 69 | + div.append('p') | ||
| 70 | + .classed('nav-me', true) | ||
| 71 | + .text(r.id) | ||
| 72 | + .on('click', nav); | ||
| 73 | + }); | ||
| 74 | + | ||
| 75 | + div = topdiv.select('.devices').select('div'); | ||
| 76 | + data.layerOrder.forEach(function (tag, idx) { | ||
| 77 | + var devs = data.devices[idx]; | ||
| 78 | + devs.forEach(function (d) { | ||
| 79 | + div.append('p') | ||
| 80 | + .text('[' + tag + '] ' + d.id); | ||
| 81 | + }); | ||
| 82 | + | ||
| 83 | + }); | ||
| 84 | + | ||
| 85 | + div = topdiv.select('.hosts').select('div'); | ||
| 86 | + data.layerOrder.forEach(function (tag, idx) { | ||
| 87 | + var hosts = data.hosts[idx]; | ||
| 88 | + hosts.forEach(function (h) { | ||
| 89 | + div.append('p') | ||
| 90 | + .text('[' + tag + '] ' + h.id); | ||
| 91 | + }); | ||
| 92 | + }); | ||
| 93 | + | ||
| 94 | + div = topdiv.select('.links').select('div'); | ||
| 95 | + var links = data.links; | ||
| 96 | + links.forEach(function (lnk) { | ||
| 97 | + div.append('p') | ||
| 98 | + .text(lnk.id); | ||
| 99 | + }); | ||
| 100 | + } | ||
| 101 | + | ||
| 102 | + function doTmpPeerRegions(data) { | ||
| 103 | + | ||
| 104 | + } | ||
| 105 | + | ||
| 38 | // ========================== Event Handlers | 106 | // ========================== Event Handlers |
| 39 | 107 | ||
| 40 | function allInstances(data) { | 108 | function allInstances(data) { |
| 41 | $log.debug('>> topo2AllInstances event:', data) | 109 | $log.debug('>> topo2AllInstances event:', data) |
| 110 | + doTmpCurrentLayout(data); | ||
| 42 | } | 111 | } |
| 43 | 112 | ||
| 44 | function currentLayout(data) { | 113 | function currentLayout(data) { |
| ... | @@ -47,6 +116,16 @@ | ... | @@ -47,6 +116,16 @@ |
| 47 | 116 | ||
| 48 | function currentRegion(data) { | 117 | function currentRegion(data) { |
| 49 | $log.debug('>> topo2CurrentRegion event:', data) | 118 | $log.debug('>> topo2CurrentRegion event:', data) |
| 119 | + doTmpCurrentRegion(data); | ||
| 120 | + } | ||
| 121 | + | ||
| 122 | + function topo2PeerRegions(data) { | ||
| 123 | + $log.debug('>> topo2PeerRegions event:', data) | ||
| 124 | + doTmpPeerRegions(data); | ||
| 125 | + } | ||
| 126 | + | ||
| 127 | + function topo2PeerRegions(data) { | ||
| 128 | + $log.debug('>> topo2PeerRegions event:', data) | ||
| 50 | } | 129 | } |
| 51 | 130 | ||
| 52 | function startDone(data) { | 131 | function startDone(data) { |
| ... | @@ -69,6 +148,7 @@ | ... | @@ -69,6 +148,7 @@ |
| 69 | topo2AllInstances: allInstances, | 148 | topo2AllInstances: allInstances, |
| 70 | topo2CurrentLayout: currentLayout, | 149 | topo2CurrentLayout: currentLayout, |
| 71 | topo2CurrentRegion: currentRegion, | 150 | topo2CurrentRegion: currentRegion, |
| 151 | + topo2PeerRegions: topo2PeerRegions, | ||
| 72 | topo2StartDone: startDone | 152 | topo2StartDone: startDone |
| 73 | }; | 153 | }; |
| 74 | }]); | 154 | }]); | ... | ... |
| 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 | + * Copyright 2016-present Open Networking Laboratory | ||
| 19 | + * | ||
| 20 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 21 | + * you may not use this file except in compliance with the License. | ||
| 22 | + * You may obtain a copy of the License at | ||
| 23 | + * | ||
| 24 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 25 | + * | ||
| 26 | + * Unless required by applicable law or agreed to in writing, software | ||
| 27 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 28 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 29 | + * See the License for the specific language governing permissions and | ||
| 30 | + * limitations under the License. | ||
| 31 | + */ | ||
| 32 | + | ||
| 33 | + | ||
| 34 | +/* | ||
| 35 | + ONOS GUI -- Topology View (theme) -- CSS file | ||
| 36 | + */ | ||
| 37 | + | ||
| 38 | +/* --- Base SVG Layer --- */ | ||
| 39 | + | ||
| 40 | +#ov-topoX svg { | ||
| 41 | + /*background-color: #f4f4f4;*/ | ||
| 42 | + background-color: goldenrod; /* just for testing */ | ||
| 43 | +} | ||
| 44 | + | ||
| 45 | +/* --- "No Devices" Layer --- */ | ||
| 46 | + | ||
| 47 | +#ov-topoX svg .noDevsBird { | ||
| 48 | + fill: #db7773; | ||
| 49 | +} | ||
| 50 | + | ||
| 51 | +#ov-topoX svg #topoX-noDevsLayer text { | ||
| 52 | + fill: #7e9aa8; | ||
| 53 | +} | ||
| 54 | + | ||
| 55 | +/* --- Topo Map --- */ | ||
| 56 | + | ||
| 57 | +#ov-topoX svg #topoX-map { | ||
| 58 | + stroke-width: 2px; | ||
| 59 | + stroke: #f4f4f4; | ||
| 60 | + fill: #e5e5e6; | ||
| 61 | +} | ||
| 62 | + |
| 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-topoX svg { | ||
| 25 | + /* prevents the little cut/copy/paste square that would appear on iPad */ | ||
| 26 | + -webkit-user-select: none; | ||
| 27 | +} | ||
| 28 | + | ||
| 29 | +/* -- TEMPORARY CSS (to be deleted) -- */ | ||
| 30 | +#topoXtmp div { | ||
| 31 | + padding: 8px 24px; | ||
| 32 | + margin: 8px; | ||
| 33 | + background-color: #ddddff; | ||
| 34 | +} | ||
| 35 | +#topoXtmp div div { | ||
| 36 | + padding: 4px 10px; | ||
| 37 | +} | ||
| 38 | + | ||
| 39 | +#topoXtmp h4 { | ||
| 40 | + margin: 0 | ||
| 41 | +} | ||
| 42 | +#topoXtmp p { | ||
| 43 | + margin: 0 | ||
| 44 | +} | ||
| 45 | +#topoXtmp .nav-me:hover { | ||
| 46 | + background-color: #bbbbdd; | ||
| 47 | +} | ||
| 48 | +#topoXtmp .nav-me { | ||
| 49 | + font-weight: bold; | ||
| 50 | + text-decoration: underline; | ||
| 51 | + cursor: pointer; | ||
| 52 | +} |
| 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 | +<!-- Topology View partial HTML --> | ||
| 18 | +<div id="ov-topoX"> | ||
| 19 | + <div id="topoXtmp"> | ||
| 20 | + <div class="parentRegion"> | ||
| 21 | + Parent Region: <span> - </span> | ||
| 22 | + </div> | ||
| 23 | + <div class="thisRegion"> | ||
| 24 | + This Region: <span> - </span> | ||
| 25 | + </div> | ||
| 26 | + <div class="subRegions"> | ||
| 27 | + <h4>Subregions</h4> | ||
| 28 | + <div></div> | ||
| 29 | + </div> | ||
| 30 | + <div class="devices"> | ||
| 31 | + <h4>Devices</h4> | ||
| 32 | + <div></div> | ||
| 33 | + </div> | ||
| 34 | + <div class="hosts"> | ||
| 35 | + <h4>Hosts</h4> | ||
| 36 | + <div></div> | ||
| 37 | + </div> | ||
| 38 | + <div class="links"> | ||
| 39 | + <h4>Links</h4> | ||
| 40 | + <div></div> | ||
| 41 | + </div> | ||
| 42 | + <div class="peers"> | ||
| 43 | + <h4>Peers</h4> | ||
| 44 | + <div></div> | ||
| 45 | + </div> | ||
| 46 | + </div> | ||
| 47 | +</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 | + * Copyright 2016-present Open Networking Laboratory | ||
| 19 | + * | ||
| 20 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 21 | + * you may not use this file except in compliance with the License. | ||
| 22 | + * You may obtain a copy of the License at | ||
| 23 | + * | ||
| 24 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
| 25 | + * | ||
| 26 | + * Unless required by applicable law or agreed to in writing, software | ||
| 27 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
| 28 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 29 | + * See the License for the specific language governing permissions and | ||
| 30 | + * limitations under the License. | ||
| 31 | + */ | ||
| 32 | + | ||
| 33 | +/* | ||
| 34 | + ONOS GUI -- Topology View Module | ||
| 35 | + | ||
| 36 | + NOTE: currently under development to support Regions. | ||
| 37 | + */ | ||
| 38 | + | ||
| 39 | +(function () { | ||
| 40 | + 'use strict'; | ||
| 41 | + | ||
| 42 | + // references to injected services | ||
| 43 | + var $scope, $log, $loc, | ||
| 44 | + fs, mast, ks, zs, | ||
| 45 | + gs, ms, sus, flash, | ||
| 46 | + wss, ps, th, | ||
| 47 | + tXes, tXfs; | ||
| 48 | + | ||
| 49 | + // DOM elements | ||
| 50 | + var ovtopoX, svg, defs, zoomLayer, mapG, spriteG, forceG, noDevsLayer; | ||
| 51 | + | ||
| 52 | + // Internal state | ||
| 53 | + var zoomer, actionMap; | ||
| 54 | + | ||
| 55 | + | ||
| 56 | + // === Helper Functions | ||
| 57 | + | ||
| 58 | + // callback invoked when the SVG view has been resized.. | ||
| 59 | + function svgResized(s) { | ||
| 60 | + $log.debug("topoX view resized", s); | ||
| 61 | + } | ||
| 62 | + | ||
| 63 | + function setUpKeys(overlayKeys) { | ||
| 64 | + $log.debug('topoX: set up keys....'); | ||
| 65 | + } | ||
| 66 | + | ||
| 67 | + // === Controller Definition ----------------------------------------- | ||
| 68 | + | ||
| 69 | + angular.module('ovTopoX', ['onosUtil', 'onosSvg', 'onosRemote']) | ||
| 70 | + .controller('OvTopoXCtrl', | ||
| 71 | + ['$scope', '$log', '$location', | ||
| 72 | + 'FnService', 'MastService', 'KeyService', 'ZoomService', | ||
| 73 | + 'GlyphService', 'MapService', 'SvgUtilService', 'FlashService', | ||
| 74 | + 'WebSocketService', 'PrefsService', 'ThemeService', | ||
| 75 | + 'TopoXEventService', 'TopoXForceService', | ||
| 76 | + | ||
| 77 | + function (_$scope_, _$log_, _$loc_, | ||
| 78 | + _fs_, _mast_, _ks_, _zs_, | ||
| 79 | + _gs_, _ms_, _sus_, _flash_, | ||
| 80 | + _wss_, _ps_, _th_, | ||
| 81 | + _tXes_, _tXfs_) { | ||
| 82 | + | ||
| 83 | + var params = _$loc_.search(), | ||
| 84 | + projection, | ||
| 85 | + dim, | ||
| 86 | + wh, | ||
| 87 | + uplink = { | ||
| 88 | + // provides function calls back into this space | ||
| 89 | + // showNoDevs: showNoDevs, | ||
| 90 | + // projection: function () { return projection; }, | ||
| 91 | + // zoomLayer: function () { return zoomLayer; }, | ||
| 92 | + // zoomer: function () { return zoomer; }, | ||
| 93 | + // opacifyMap: opacifyMap, | ||
| 94 | + // topoStartDone: topoStartDone | ||
| 95 | + }; | ||
| 96 | + | ||
| 97 | + $scope = _$scope_; | ||
| 98 | + $log = _$log_; | ||
| 99 | + $loc = _$loc_; | ||
| 100 | + | ||
| 101 | + fs = _fs_; | ||
| 102 | + mast = _mast_; | ||
| 103 | + ks = _ks_; | ||
| 104 | + zs = _zs_; | ||
| 105 | + | ||
| 106 | + gs = _gs_; | ||
| 107 | + ms = _ms_; | ||
| 108 | + sus = _sus_; | ||
| 109 | + flash = _flash_; | ||
| 110 | + | ||
| 111 | + wss = _wss_; | ||
| 112 | + ps = _ps_; | ||
| 113 | + th = _th_; | ||
| 114 | + | ||
| 115 | + tXes = _tXes_; | ||
| 116 | + tXfs = _tXfs_; | ||
| 117 | + | ||
| 118 | + // capture selected intent parameters (if they are set in the | ||
| 119 | + // query string) so that the traffic overlay can highlight | ||
| 120 | + // the path for that intent | ||
| 121 | + if (params.intentKey && params.intentAppId && params.intentAppName) { | ||
| 122 | + $scope.intentData = { | ||
| 123 | + key: params.intentKey, | ||
| 124 | + appId: params.intentAppId, | ||
| 125 | + appName: params.intentAppName | ||
| 126 | + }; | ||
| 127 | + } | ||
| 128 | + | ||
| 129 | + $scope.notifyResize = function () { | ||
| 130 | + svgResized(fs.windowSize(mast.mastHeight())); | ||
| 131 | + }; | ||
| 132 | + | ||
| 133 | + // Cleanup on destroyed scope.. | ||
| 134 | + $scope.$on('$destroy', function () { | ||
| 135 | + $log.log('OvTopoXCtrl is saying Buh-Bye!'); | ||
| 136 | + tXes.stop(); | ||
| 137 | + ks.unbindKeys(); | ||
| 138 | + tXfs.destroy(); | ||
| 139 | + }); | ||
| 140 | + | ||
| 141 | + // svg layer and initialization of components | ||
| 142 | + ovtopoX = d3.select('#ov-topoX'); | ||
| 143 | + svg = ovtopoX.select('svg'); | ||
| 144 | + // set the svg size to match that of the window, less the masthead | ||
| 145 | + wh = fs.windowSize(mast.mastHeight()); | ||
| 146 | + $log.debug('setting topo SVG size to', wh); | ||
| 147 | + svg.attr(wh); | ||
| 148 | + dim = [wh.width, wh.height]; | ||
| 149 | + | ||
| 150 | + | ||
| 151 | + // set up our keyboard shortcut bindings | ||
| 152 | + setUpKeys(); | ||
| 153 | + | ||
| 154 | + // make sure we can respond to topology events from the server | ||
| 155 | + tXes.bindHandlers(); | ||
| 156 | + | ||
| 157 | + // initialize the force layout, ready to render the topology | ||
| 158 | + tXfs.init(); | ||
| 159 | + | ||
| 160 | + | ||
| 161 | + // =-=-=-=-=-=-=-=- | ||
| 162 | + // TODO: in future, we will load background map data | ||
| 163 | + // asynchronously (hence the promise) and then chain off | ||
| 164 | + // there to send the topoXstart event to the server. | ||
| 165 | + // For now, we'll send the event inline... | ||
| 166 | + tXes.start(); | ||
| 167 | + | ||
| 168 | + | ||
| 169 | + // === ORIGINAL CODE === | ||
| 170 | + | ||
| 171 | + // setUpKeys(); | ||
| 172 | + // setUpToolbar(); | ||
| 173 | + // setUpDefs(); | ||
| 174 | + // setUpZoom(); | ||
| 175 | + // setUpNoDevs(); | ||
| 176 | + /* | ||
| 177 | + setUpMap().then( | ||
| 178 | + function (proj) { | ||
| 179 | + var z = ps.getPrefs('topo_zoom', { tx:0, ty:0, sc:1 }); | ||
| 180 | + zoomer.panZoom([z.tx, z.ty], z.sc); | ||
| 181 | + $log.debug('** Zoom restored:', z); | ||
| 182 | + | ||
| 183 | + projection = proj; | ||
| 184 | + $log.debug('** We installed the projection:', proj); | ||
| 185 | + flash.enable(false); | ||
| 186 | + toggleMap(prefsState.bg); | ||
| 187 | + flash.enable(true); | ||
| 188 | + mapShader(true); | ||
| 189 | + | ||
| 190 | + // now we have the map projection, we are ready for | ||
| 191 | + // the server to send us device/host data... | ||
| 192 | + tes.start(); | ||
| 193 | + // need to do the following so we immediately get | ||
| 194 | + // the summary panel data back from the server | ||
| 195 | + restoreSummaryFromPrefs(); | ||
| 196 | + } | ||
| 197 | + ); | ||
| 198 | + */ | ||
| 199 | + // tes.bindHandlers(); | ||
| 200 | + // setUpSprites(); | ||
| 201 | + | ||
| 202 | + // forceG = zoomLayer.append('g').attr('id', 'topo-force'); | ||
| 203 | + // tfs.initForce(svg, forceG, uplink, dim); | ||
| 204 | + // tis.initInst({ showMastership: tfs.showMastership }); | ||
| 205 | + // tps.initPanels(); | ||
| 206 | + | ||
| 207 | + // restoreConfigFromPrefs(); | ||
| 208 | + // ttbs.setDefaultOverlay(prefsState.ovidx); | ||
| 209 | + | ||
| 210 | + // $log.debug('registered overlays...', tov.list()); | ||
| 211 | + | ||
| 212 | + $log.log('OvTopoXCtrl has been created'); | ||
| 213 | + }]); | ||
| 214 | +}()); |
| 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, tXfs; | ||
| 31 | + | ||
| 32 | + // internal state | ||
| 33 | + var handlerMap, | ||
| 34 | + openListener; | ||
| 35 | + | ||
| 36 | + // ========================== Helper Functions | ||
| 37 | + | ||
| 38 | + function createHandlerMap() { | ||
| 39 | + handlerMap = { | ||
| 40 | + topo2AllInstances: tXfs, | ||
| 41 | + topo2CurrentLayout: tXfs, | ||
| 42 | + topo2CurrentRegion: tXfs, | ||
| 43 | + topo2PeerRegions: tXfs, | ||
| 44 | + topo2StartDone: tXfs | ||
| 45 | + | ||
| 46 | + // Add further event names / module references as needed | ||
| 47 | + }; | ||
| 48 | + } | ||
| 49 | + | ||
| 50 | + function wsOpen(host, url) { | ||
| 51 | + $log.debug('topoXEvent: WSopen - cluster node:', host, 'URL:', url); | ||
| 52 | + // tell the server we are ready to receive topo events | ||
| 53 | + wss.sendEvent('topo2Start'); | ||
| 54 | + } | ||
| 55 | + | ||
| 56 | + // bind our event handlers to the web socket service, so that our | ||
| 57 | + // callbacks get invoked for incoming events | ||
| 58 | + function bindHandlers() { | ||
| 59 | + wss.bindHandlers(handlerMap); | ||
| 60 | + $log.debug('topoX event handlers bound'); | ||
| 61 | + } | ||
| 62 | + | ||
| 63 | + // tell the server we are ready to receive topology events | ||
| 64 | + function start() { | ||
| 65 | + // in case we fail over to a new server, | ||
| 66 | + // listen for wsock-open events | ||
| 67 | + openListener = wss.addOpenListener(wsOpen); | ||
| 68 | + wss.sendEvent('topo2Start'); | ||
| 69 | + $log.debug('topoX comms started'); | ||
| 70 | + } | ||
| 71 | + | ||
| 72 | + // tell the server we no longer wish to receive topology events | ||
| 73 | + function stop() { | ||
| 74 | + wss.sendEvent('topo2Stop'); | ||
| 75 | + wss.unbindHandlers(handlerMap); | ||
| 76 | + wss.removeOpenListener(openListener); | ||
| 77 | + openListener = null; | ||
| 78 | + $log.debug('topoX comms stopped'); | ||
| 79 | + } | ||
| 80 | + | ||
| 81 | + // ========================== Main Service Definition | ||
| 82 | + | ||
| 83 | + angular.module('ovTopoX') | ||
| 84 | + .factory('TopoXEventService', | ||
| 85 | + ['$log', 'WebSocketService', 'TopoXForceService', | ||
| 86 | + | ||
| 87 | + function (_$log_, _wss_, _tXfs_) { | ||
| 88 | + $log = _$log_; | ||
| 89 | + wss = _wss_; | ||
| 90 | + tXfs = _tXfs_; | ||
| 91 | + | ||
| 92 | + // deferred creation of handler map, so module references are good | ||
| 93 | + createHandlerMap(); | ||
| 94 | + | ||
| 95 | + return { | ||
| 96 | + bindHandlers: bindHandlers, | ||
| 97 | + start: start, | ||
| 98 | + stop: stop | ||
| 99 | + }; | ||
| 100 | + }]); | ||
| 101 | +}()); |
| 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 | + // ========================== Temporary Code (to be deleted later) | ||
| 39 | + | ||
| 40 | + function request(dir, rid) { | ||
| 41 | + wss.sendEvent('topo2navRegion', { | ||
| 42 | + dir: dir, | ||
| 43 | + rid: rid | ||
| 44 | + }); | ||
| 45 | + } | ||
| 46 | + | ||
| 47 | + function doTmpCurrentLayout(data) { | ||
| 48 | + var topdiv = d3.select('#topoXtmp'); | ||
| 49 | + var parentRegion = data.parent; | ||
| 50 | + var span = topdiv.select('.parentRegion').select('span'); | ||
| 51 | + span.text(parentRegion || '[no parent]'); | ||
| 52 | + span.classed('nav-me', !!parentRegion); | ||
| 53 | + } | ||
| 54 | + | ||
| 55 | + function doTmpCurrentRegion(data) { | ||
| 56 | + var topdiv = d3.select('#topoXtmp'); | ||
| 57 | + var span = topdiv.select('.thisRegion').select('span'); | ||
| 58 | + var div; | ||
| 59 | + | ||
| 60 | + span.text(data.id); | ||
| 61 | + | ||
| 62 | + div = topdiv.select('.subRegions').select('div'); | ||
| 63 | + data.subregions.forEach(function (r) { | ||
| 64 | + | ||
| 65 | + function nav() { | ||
| 66 | + request('down', r.id); | ||
| 67 | + } | ||
| 68 | + | ||
| 69 | + div.append('p') | ||
| 70 | + .classed('nav-me', true) | ||
| 71 | + .text(r.id) | ||
| 72 | + .on('click', nav); | ||
| 73 | + }); | ||
| 74 | + | ||
| 75 | + div = topdiv.select('.devices').select('div'); | ||
| 76 | + data.layerOrder.forEach(function (tag, idx) { | ||
| 77 | + var devs = data.devices[idx]; | ||
| 78 | + devs.forEach(function (d) { | ||
| 79 | + div.append('p') | ||
| 80 | + .text('[' + tag + '] ' + d.id); | ||
| 81 | + }); | ||
| 82 | + | ||
| 83 | + }); | ||
| 84 | + | ||
| 85 | + div = topdiv.select('.hosts').select('div'); | ||
| 86 | + data.layerOrder.forEach(function (tag, idx) { | ||
| 87 | + var hosts = data.hosts[idx]; | ||
| 88 | + hosts.forEach(function (h) { | ||
| 89 | + div.append('p') | ||
| 90 | + .text('[' + tag + '] ' + h.id); | ||
| 91 | + }); | ||
| 92 | + }); | ||
| 93 | + | ||
| 94 | + div = topdiv.select('.links').select('div'); | ||
| 95 | + var links = data.links; | ||
| 96 | + links.forEach(function (lnk) { | ||
| 97 | + div.append('p') | ||
| 98 | + .text(lnk.id); | ||
| 99 | + }); | ||
| 100 | + } | ||
| 101 | + | ||
| 102 | + function doTmpPeerRegions(data) { | ||
| 103 | + | ||
| 104 | + } | ||
| 105 | + | ||
| 106 | + // ========================== Event Handlers | ||
| 107 | + | ||
| 108 | + function allInstances(data) { | ||
| 109 | + $log.debug('>> topo2AllInstances event:', data) | ||
| 110 | + doTmpCurrentLayout(data); | ||
| 111 | + } | ||
| 112 | + | ||
| 113 | + function currentLayout(data) { | ||
| 114 | + $log.debug('>> topo2CurrentLayout event:', data) | ||
| 115 | + } | ||
| 116 | + | ||
| 117 | + function currentRegion(data) { | ||
| 118 | + $log.debug('>> topo2CurrentRegion event:', data) | ||
| 119 | + doTmpCurrentRegion(data); | ||
| 120 | + } | ||
| 121 | + | ||
| 122 | + function peerRegions(data) { | ||
| 123 | + $log.debug('>> topo2PeerRegions event:', data) | ||
| 124 | + doTmpPeerRegions(data); | ||
| 125 | + } | ||
| 126 | + | ||
| 127 | + function startDone(data) { | ||
| 128 | + $log.debug('>> topo2StartDone event:', data) | ||
| 129 | + } | ||
| 130 | + | ||
| 131 | + // ========================== Main Service Definition | ||
| 132 | + | ||
| 133 | + angular.module('ovTopoX') | ||
| 134 | + .factory('TopoXForceService', | ||
| 135 | + ['$log', 'WebSocketService', | ||
| 136 | + | ||
| 137 | + function (_$log_, _wss_) { | ||
| 138 | + $log = _$log_; | ||
| 139 | + wss = _wss_; | ||
| 140 | + | ||
| 141 | + return { | ||
| 142 | + init: init, | ||
| 143 | + destroy: destroy, | ||
| 144 | + topo2AllInstances: allInstances, | ||
| 145 | + topo2CurrentLayout: currentLayout, | ||
| 146 | + topo2CurrentRegion: currentRegion, | ||
| 147 | + topo2PeerRegions: peerRegions, | ||
| 148 | + topo2StartDone: startDone | ||
| 149 | + }; | ||
| 150 | + }]); | ||
| 151 | +}()); |
| ... | @@ -133,6 +133,12 @@ | ... | @@ -133,6 +133,12 @@ |
| 133 | <link rel="stylesheet" href="app/view/topo2/topo2.css"> | 133 | <link rel="stylesheet" href="app/view/topo2/topo2.css"> |
| 134 | <link rel="stylesheet" href="app/view/topo2/topo2-theme.css"> | 134 | <link rel="stylesheet" href="app/view/topo2/topo2-theme.css"> |
| 135 | 135 | ||
| 136 | + <script src="app/view/topoX/topoX.js"></script> | ||
| 137 | + <script src="app/view/topoX/topoXEvent.js"></script> | ||
| 138 | + <script src="app/view/topoX/topoXForce.js"></script> | ||
| 139 | + <link rel="stylesheet" href="app/view/topoX/topoX.css"> | ||
| 140 | + <link rel="stylesheet" href="app/view/topoX/topoX-theme.css"> | ||
| 141 | + | ||
| 136 | <!-- Builtin views javascript. --> | 142 | <!-- Builtin views javascript. --> |
| 137 | <script src="app/view/topo/topo.js"></script> | 143 | <script src="app/view/topo/topo.js"></script> |
| 138 | <script src="app/view/topo/topoD3.js"></script> | 144 | <script src="app/view/topo/topoD3.js"></script> | ... | ... |
| ... | @@ -4,9 +4,11 @@ | ... | @@ -4,9 +4,11 @@ |
| 4 | "id": "<null-region>", | 4 | "id": "<null-region>", |
| 5 | "subregions": [{ | 5 | "subregions": [{ |
| 6 | "id": "r2", | 6 | "id": "r2", |
| 7 | + "nodeType":"region", | ||
| 7 | "nDevs": 2 | 8 | "nDevs": 2 |
| 8 | }, { | 9 | }, { |
| 9 | "id": "r1", | 10 | "id": "r1", |
| 11 | + "nodeType":"region", | ||
| 10 | "nDevs": 3 | 12 | "nDevs": 3 |
| 11 | }], | 13 | }], |
| 12 | "devices": [ | 14 | "devices": [ |
| ... | @@ -14,6 +16,7 @@ | ... | @@ -14,6 +16,7 @@ |
| 14 | [], | 16 | [], |
| 15 | [{ | 17 | [{ |
| 16 | "id": "null:0000000000000001", | 18 | "id": "null:0000000000000001", |
| 19 | + "nodeType":"device", | ||
| 17 | "type": "switch", | 20 | "type": "switch", |
| 18 | "online": false, | 21 | "online": false, |
| 19 | "master": "", | 22 | "master": "", | ... | ... |
-
Please register or login to post a comment