mirror of
https://github.com/opennetworkinglab/onos.git
synced 2025-10-23 13:21:21 +02:00
ONOS-2186 - GUI Topo Overlay - (WIP)
- Showing traffic on selected intent now subdues other elements. - Augmented Highlights to allow for retrieval by ID. - Reparented HostHighlight and DeviceHighlight to NodeHighlight. - Added a few extra highlight unit tests. Change-Id: I0de1cefdcfda58a6fec6e90be5fe898d35aa1b37
This commit is contained in:
parent
1c15287d06
commit
94f7daec34
@ -20,7 +20,7 @@ package org.onosproject.ui.topo;
|
||||
/**
|
||||
* Denotes the highlighting to apply to a device.
|
||||
*/
|
||||
public class DeviceHighlight extends AbstractHighlight {
|
||||
public class DeviceHighlight extends NodeHighlight {
|
||||
|
||||
public DeviceHighlight(String deviceId) {
|
||||
super(TopoElementType.DEVICE, deviceId);
|
||||
|
@ -17,9 +17,10 @@
|
||||
|
||||
package org.onosproject.ui.topo;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
@ -53,9 +54,9 @@ public class Highlights {
|
||||
}
|
||||
}
|
||||
|
||||
private final Set<DeviceHighlight> devices = new HashSet<>();
|
||||
private final Set<HostHighlight> hosts = new HashSet<>();
|
||||
private final Set<LinkHighlight> links = new HashSet<>();
|
||||
private final Map<String, DeviceHighlight> devices = new HashMap<>();
|
||||
private final Map<String, HostHighlight> hosts = new HashMap<>();
|
||||
private final Map<String, LinkHighlight> links = new HashMap<>();
|
||||
|
||||
private Amount subdueLevel = Amount.ZERO;
|
||||
|
||||
@ -67,7 +68,7 @@ public class Highlights {
|
||||
* @return self, for chaining
|
||||
*/
|
||||
public Highlights add(DeviceHighlight dh) {
|
||||
devices.add(dh);
|
||||
devices.put(dh.elementId(), dh);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -78,7 +79,7 @@ public class Highlights {
|
||||
* @return self, for chaining
|
||||
*/
|
||||
public Highlights add(HostHighlight hh) {
|
||||
hosts.add(hh);
|
||||
hosts.put(hh.elementId(), hh);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -89,7 +90,7 @@ public class Highlights {
|
||||
* @return self, for chaining
|
||||
*/
|
||||
public Highlights add(LinkHighlight lh) {
|
||||
links.add(lh);
|
||||
links.put(lh.elementId(), lh);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -106,30 +107,30 @@ public class Highlights {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the set of device highlights.
|
||||
* Returns the collection of device highlights.
|
||||
*
|
||||
* @return device highlights
|
||||
*/
|
||||
public Set<DeviceHighlight> devices() {
|
||||
return Collections.unmodifiableSet(devices);
|
||||
public Collection<DeviceHighlight> devices() {
|
||||
return Collections.unmodifiableCollection(devices.values());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the set of host highlights.
|
||||
* Returns the collection of host highlights.
|
||||
*
|
||||
* @return host highlights
|
||||
*/
|
||||
public Set<HostHighlight> hosts() {
|
||||
return Collections.unmodifiableSet(hosts);
|
||||
public Collection<HostHighlight> hosts() {
|
||||
return Collections.unmodifiableCollection(hosts.values());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the set of link highlights.
|
||||
* Returns the collection of link highlights.
|
||||
*
|
||||
* @return link highlights
|
||||
*/
|
||||
public Set<LinkHighlight> links() {
|
||||
return Collections.unmodifiableSet(links);
|
||||
public Collection<LinkHighlight> links() {
|
||||
return Collections.unmodifiableCollection(links.values());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -141,4 +142,49 @@ public class Highlights {
|
||||
public Amount subdueLevel() {
|
||||
return subdueLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the node highlight (device or host) for the given element
|
||||
* identifier, or null if no match.
|
||||
*
|
||||
* @param id element identifier
|
||||
* @return corresponding node highlight
|
||||
*/
|
||||
public NodeHighlight getNode(String id) {
|
||||
NodeHighlight nh = devices.get(id);
|
||||
return nh != null ? nh : hosts.get(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the device highlight for the given device identifier,
|
||||
* or null if no match.
|
||||
*
|
||||
* @param id device identifier
|
||||
* @return corresponding device highlight
|
||||
*/
|
||||
public DeviceHighlight getDevice(String id) {
|
||||
return devices.get(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the host highlight for the given host identifier,
|
||||
* or null if no match.
|
||||
*
|
||||
* @param id host identifier
|
||||
* @return corresponding host highlight
|
||||
*/
|
||||
public HostHighlight getHost(String id) {
|
||||
return hosts.get(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the link highlight for the given link identifier,
|
||||
* or null if no match.
|
||||
*
|
||||
* @param id link identifier
|
||||
* @return corresponding link highlight
|
||||
*/
|
||||
public LinkHighlight getLink(String id) {
|
||||
return links.get(id);
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ package org.onosproject.ui.topo;
|
||||
/**
|
||||
* Denotes the highlighting to apply to a host.
|
||||
*/
|
||||
public class HostHighlight extends AbstractHighlight {
|
||||
public class HostHighlight extends NodeHighlight {
|
||||
|
||||
public HostHighlight(String hostId) {
|
||||
super(TopoElementType.HOST, hostId);
|
||||
|
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2015 Open Networking Laboratory
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.onosproject.ui.topo;
|
||||
|
||||
/**
|
||||
* Parent class of {@link DeviceHighlight} and {@link HostHighlight}.
|
||||
*/
|
||||
public abstract class NodeHighlight extends AbstractHighlight {
|
||||
public NodeHighlight(TopoElementType type, String elementId) {
|
||||
super(type, elementId);
|
||||
}
|
||||
}
|
@ -17,28 +17,75 @@
|
||||
|
||||
package org.onosproject.ui.topo;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.onosproject.ui.topo.Highlights.Amount;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link Highlights}.
|
||||
*/
|
||||
public class HighlightsTest {
|
||||
|
||||
private Highlights hl;
|
||||
private static final String DEV_1 = "dev-1";
|
||||
private static final String DEV_2 = "dev-2";
|
||||
private static final String HOST_A = "Host...A";
|
||||
|
||||
private Highlights highlights;
|
||||
private DeviceHighlight dh1;
|
||||
private DeviceHighlight dh2;
|
||||
private HostHighlight hha;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
highlights = new Highlights();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void basic() {
|
||||
hl = new Highlights();
|
||||
assertEquals("devices", 0, highlights.devices().size());
|
||||
assertEquals("hosts", 0, highlights.hosts().size());
|
||||
assertEquals("links", 0, highlights.links().size());
|
||||
assertEquals("sudue", Amount.ZERO, highlights.subdueLevel());
|
||||
}
|
||||
|
||||
assertEquals("devices", 0, hl.devices().size());
|
||||
assertEquals("hosts", 0, hl.hosts().size());
|
||||
assertEquals("links", 0, hl.links().size());
|
||||
assertEquals("sudue", Highlights.Amount.ZERO, hl.subdueLevel());
|
||||
@Test
|
||||
public void coupleOfDevices() {
|
||||
dh1 = new DeviceHighlight(DEV_1);
|
||||
dh2 = new DeviceHighlight(DEV_2);
|
||||
|
||||
highlights.add(dh1);
|
||||
highlights.add(dh2);
|
||||
assertTrue("missing dh1", highlights.devices().contains(dh1));
|
||||
assertTrue("missing dh2", highlights.devices().contains(dh2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void alternateSubdue() {
|
||||
highlights.subdueAllElse(Amount.MINIMALLY);
|
||||
assertEquals("wrong level", Amount.MINIMALLY, highlights.subdueLevel());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void highlightRetrieval() {
|
||||
dh1 = new DeviceHighlight(DEV_1);
|
||||
hha = new HostHighlight(HOST_A);
|
||||
highlights.add(dh1)
|
||||
.add(hha);
|
||||
|
||||
assertNull("dev as host", highlights.getHost(DEV_1));
|
||||
assertNull("host as dev", highlights.getDevice(HOST_A));
|
||||
|
||||
assertEquals("missed dev as dev", dh1, highlights.getDevice(DEV_1));
|
||||
assertEquals("missed dev as node", dh1, highlights.getNode(DEV_1));
|
||||
|
||||
assertEquals("missed host as host", hha, highlights.getHost(HOST_A));
|
||||
assertEquals("missed host as node", hha, highlights.getNode(HOST_A));
|
||||
}
|
||||
|
||||
// NOTE: further unit tests involving the Highlights class are done
|
||||
// in TopoJsonTest.
|
||||
|
||||
}
|
||||
|
@ -20,7 +20,9 @@ package org.onosproject.ui.impl;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import org.onosproject.net.Device;
|
||||
import org.onosproject.net.DeviceId;
|
||||
import org.onosproject.net.ElementId;
|
||||
import org.onosproject.net.Host;
|
||||
import org.onosproject.net.HostId;
|
||||
import org.onosproject.net.Link;
|
||||
import org.onosproject.net.PortNumber;
|
||||
import org.onosproject.net.flow.FlowEntry;
|
||||
@ -40,8 +42,12 @@ import org.onosproject.ui.impl.topo.TopoIntentFilter;
|
||||
import org.onosproject.ui.impl.topo.TrafficLink;
|
||||
import org.onosproject.ui.impl.topo.TrafficLink.StatsType;
|
||||
import org.onosproject.ui.impl.topo.TrafficLinkMap;
|
||||
import org.onosproject.ui.topo.DeviceHighlight;
|
||||
import org.onosproject.ui.topo.Highlights;
|
||||
import org.onosproject.ui.topo.Highlights.Amount;
|
||||
import org.onosproject.ui.topo.HostHighlight;
|
||||
import org.onosproject.ui.topo.LinkHighlight.Flavor;
|
||||
import org.onosproject.ui.topo.NodeHighlight;
|
||||
import org.onosproject.ui.topo.NodeSelection;
|
||||
import org.onosproject.ui.topo.TopoUtils;
|
||||
import org.slf4j.Logger;
|
||||
@ -59,9 +65,7 @@ import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
import static org.onosproject.net.DefaultEdgeLink.createEdgeLink;
|
||||
import static org.onosproject.ui.impl.TrafficMonitor.Mode.IDLE;
|
||||
import static org.onosproject.ui.impl.TrafficMonitor.Mode.RELATED_INTENTS;
|
||||
import static org.onosproject.ui.impl.TrafficMonitor.Mode.SELECTED_INTENT;
|
||||
import static org.onosproject.ui.impl.TrafficMonitor.Mode.*;
|
||||
|
||||
/**
|
||||
* Encapsulates the behavior of monitoring specific traffic patterns.
|
||||
@ -442,6 +446,7 @@ public class TrafficMonitor {
|
||||
current.id(), selectedIntents.index(), selectedIntents.size());
|
||||
|
||||
highlightIntentLinksWithTraffic(highlights, primary);
|
||||
highlights.subdueAllElse(Amount.MINIMALLY);
|
||||
}
|
||||
return highlights;
|
||||
}
|
||||
@ -540,19 +545,20 @@ public class TrafficMonitor {
|
||||
TrafficLinkMap linkMap = new TrafficLinkMap();
|
||||
// NOTE: highlight secondary first, then primary, so that links shared
|
||||
// by intents are colored correctly ("last man wins")
|
||||
createTrafficLinks(linkMap, secondary, Flavor.SECONDARY_HIGHLIGHT, false);
|
||||
createTrafficLinks(linkMap, primary, Flavor.PRIMARY_HIGHLIGHT, false);
|
||||
createTrafficLinks(highlights, linkMap, secondary, Flavor.SECONDARY_HIGHLIGHT, false);
|
||||
createTrafficLinks(highlights, linkMap, primary, Flavor.PRIMARY_HIGHLIGHT, false);
|
||||
colorLinks(highlights, linkMap);
|
||||
}
|
||||
|
||||
private void highlightIntentLinksWithTraffic(Highlights highlights,
|
||||
Set<Intent> primary) {
|
||||
TrafficLinkMap linkMap = new TrafficLinkMap();
|
||||
createTrafficLinks(linkMap, primary, Flavor.PRIMARY_HIGHLIGHT, true);
|
||||
createTrafficLinks(highlights, linkMap, primary, Flavor.PRIMARY_HIGHLIGHT, true);
|
||||
colorLinks(highlights, linkMap);
|
||||
}
|
||||
|
||||
private void createTrafficLinks(TrafficLinkMap linkMap, Set<Intent> intents,
|
||||
private void createTrafficLinks(Highlights highlights,
|
||||
TrafficLinkMap linkMap, Set<Intent> intents,
|
||||
Flavor flavor, boolean showTraffic) {
|
||||
for (Intent intent : intents) {
|
||||
List<Intent> installables = servicesBundle.intentService()
|
||||
@ -573,11 +579,33 @@ public class TrafficMonitor {
|
||||
|
||||
boolean isOptical = intent instanceof OpticalConnectivityIntent;
|
||||
processLinks(linkMap, links, flavor, isOptical, showTraffic);
|
||||
updateHighlights(highlights, links);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateHighlights(Highlights highlights, Iterable<Link> links) {
|
||||
for (Link link : links) {
|
||||
ensureNodePresent(highlights, link.src().elementId());
|
||||
ensureNodePresent(highlights, link.dst().elementId());
|
||||
}
|
||||
}
|
||||
|
||||
private void ensureNodePresent(Highlights highlights, ElementId eid) {
|
||||
String id = eid.toString();
|
||||
NodeHighlight nh = highlights.getNode(id);
|
||||
if (nh == null) {
|
||||
if (eid instanceof DeviceId) {
|
||||
nh = new DeviceHighlight(id);
|
||||
highlights.add((DeviceHighlight) nh);
|
||||
} else if (eid instanceof HostId) {
|
||||
nh = new HostHighlight(id);
|
||||
highlights.add((HostHighlight) nh);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Extracts links from the specified flow rule intent resources
|
||||
private Collection<Link> linkResources(Intent installable) {
|
||||
ImmutableList.Builder<Link> builder = ImmutableList.builder();
|
||||
|
@ -90,13 +90,13 @@ public final class TopoJson {
|
||||
}
|
||||
|
||||
private static ObjectNode json(DeviceHighlight dh) {
|
||||
// TODO: implement this once we know what a device highlight looks like
|
||||
return objectNode();
|
||||
return objectNode()
|
||||
.put(ID, dh.elementId());
|
||||
}
|
||||
|
||||
private static ObjectNode json(HostHighlight hh) {
|
||||
// TODO: implement this once we know what a host highlight looks like
|
||||
return objectNode();
|
||||
return objectNode()
|
||||
.put(ID, hh.elementId());
|
||||
}
|
||||
|
||||
private static ObjectNode json(LinkHighlight lh) {
|
||||
|
@ -242,6 +242,10 @@
|
||||
|
||||
// ========================
|
||||
|
||||
function nodeById(id) {
|
||||
return lu[id];
|
||||
}
|
||||
|
||||
function makeNodeKey(node1, node2) {
|
||||
return node1 + '-' + node2;
|
||||
}
|
||||
@ -515,10 +519,10 @@
|
||||
});
|
||||
}
|
||||
|
||||
function unsuppressLink(id, less) {
|
||||
function unsuppressLink(key, less) {
|
||||
var cls = supAmt(less);
|
||||
link.each(function (n) {
|
||||
if (n.id === id) {
|
||||
if (n.key === key) {
|
||||
n.el.classed(cls, false);
|
||||
}
|
||||
});
|
||||
@ -922,6 +926,7 @@
|
||||
clearLinkTrafficStyle: clearLinkTrafficStyle,
|
||||
removeLinkLabels: removeLinkLabels,
|
||||
findLinkById: tms.findLinkById,
|
||||
findNodeById: nodeById,
|
||||
updateLinks: updateLinks,
|
||||
updateNodes: updateNodes,
|
||||
supLayers: suppressLayers,
|
||||
|
@ -301,11 +301,12 @@
|
||||
clearLinkTrafficStyle()
|
||||
removeLinkLabels()
|
||||
findLinkById( id )
|
||||
findNodeById( id )
|
||||
updateLinks()
|
||||
updateNodes()
|
||||
supLayers( bool, [less] )
|
||||
unsupNode( id, [less] )
|
||||
unsupLink( id, [less] )
|
||||
unsupLink( key, [less] )
|
||||
*/
|
||||
|
||||
// TODO: clear node highlighting
|
||||
@ -322,16 +323,30 @@
|
||||
api.supLayers(false, true);
|
||||
}
|
||||
|
||||
// TODO: device and host highlights
|
||||
data.hosts.forEach(function (host) {
|
||||
var hdata = api.findNodeById(host.id);
|
||||
if (hdata && !hdata.el.empty()) {
|
||||
api.unsupNode(hdata.id, less);
|
||||
// TODO: further highlighting?
|
||||
}
|
||||
});
|
||||
|
||||
data.links.forEach(function (lnk) {
|
||||
var ldata = api.findLinkById(lnk.id),
|
||||
lab = lnk.label,
|
||||
data.devices.forEach(function (device) {
|
||||
var ddata = api.findNodeById(device.id);
|
||||
if (ddata && !ddata.el.empty()) {
|
||||
api.unsupNode(ddata.id, less);
|
||||
// TODO: further highlighting?
|
||||
}
|
||||
});
|
||||
|
||||
data.links.forEach(function (link) {
|
||||
var ldata = api.findLinkById(link.id),
|
||||
lab = link.label,
|
||||
units, portcls, magnitude;
|
||||
|
||||
if (ldata && !ldata.el.empty()) {
|
||||
api.unsupLink(ldata.id, less);
|
||||
ldata.el.classed(lnk.css, true);
|
||||
api.unsupLink(ldata.key, less);
|
||||
ldata.el.classed(link.css, true);
|
||||
ldata.label = lab;
|
||||
|
||||
// inject additional styling for port-based traffic
|
||||
|
Loading…
x
Reference in New Issue
Block a user