[ONOS-4159] PCE Web GUI implementation: Tunnel highlight and defect fixes
Change-Id: I385c00d4654e746133f0d9757511e3a8821fad7a
diff --git a/apps/pce/pceweb/src/main/java/org/onosproject/pceweb/PceWebTopovMessageHandler.java b/apps/pce/pceweb/src/main/java/org/onosproject/pceweb/PceWebTopovMessageHandler.java
index 16ce224..1aa0f1d 100644
--- a/apps/pce/pceweb/src/main/java/org/onosproject/pceweb/PceWebTopovMessageHandler.java
+++ b/apps/pce/pceweb/src/main/java/org/onosproject/pceweb/PceWebTopovMessageHandler.java
@@ -36,8 +36,11 @@
import org.onosproject.ui.UiMessageHandler;
import org.onosproject.ui.topo.DeviceHighlight;
import org.onosproject.ui.topo.Highlights;
+import org.onosproject.ui.topo.LinkHighlight;
+import org.onosproject.ui.topo.Mod;
import org.onosproject.ui.topo.NodeBadge;
import org.onosproject.ui.topo.TopoJson;
+import org.onosproject.ui.topo.TopoUtils;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.intent.Constraint;
import org.onosproject.pce.pceservice.LspType;
@@ -53,6 +56,7 @@
import org.onosproject.incubator.net.tunnel.TunnelId;
import org.onosproject.incubator.net.tunnel.TunnelListener;
import org.onosproject.incubator.net.tunnel.TunnelService;
+import static org.onosproject.ui.topo.LinkHighlight.Flavor.*;
import static org.onosproject.incubator.net.tunnel.Tunnel.Type.MPLS;
import com.fasterxml.jackson.databind.node.ArrayNode;
@@ -68,8 +72,6 @@
public class PceWebTopovMessageHandler extends UiMessageHandler {
private static final String PCEWEB_CLEAR = "pceTopovClear";
- private static final String PCEWEB_SET_SRC = "pceTopovSetSrc";
- private static final String PCEWEB_SET_DST = "pceTopovSetDst";
private static final String PCEWEB_SET_PATH = "pceTopovSetMode";
private static final String PCEWEB_UPDATE_PATH_QUERY = "pceTopovUpdateQuery";
private static final String PCEWEB_UPDATE_PATH = "pceTopovUpdate";
@@ -78,11 +80,10 @@
private static final String PCEWEB_QUERY_TUNNELS = "pceTopovTunnelDisplay";
private static final String PCEWEB_SHOW_TUNNEL = "pceTopovShowTunnels";
private static final String PCEWEB_SHOW_TUNNEL_REMOVE = "pceTopovShowTunnelsRem";
- private static final String ID = "id";
- private static final String TYPE = "type";
- private static final String ROUTER = "router";
- private static final String DST = "Egress";
- private static final String SRC = "Ingress";
+ private static final String PCEWEB_TUNNEL_UPDATE_INFO = "updatePathmsgInfo";
+ private static final String PCEWEB_TUNNEL_UPDATE_INFO_REPLY = "pceTopovShowTunnelsUpdate";
+ private static final String DST = "DST";
+ private static final String SRC = "SRC";
private static final String BANDWIDTH = "bw";
private static final String BANDWIDTHTYPE = "bwtype";
private static final String COSTTYPE = "ctype";
@@ -94,6 +95,7 @@
private static final String COST_TYPE_IGP = "igp";
private static final String COST_TYPE_TE = "te";
private static final String BANDWIDTH_TYPE_KBPS = "kbps";
+ private static final String BANDWIDTH_TYPE_MBPS = "kbps";
private static final String BUFFER_ARRAY = "a";
private static final String BANDWIDTH_BPS = "BPS";
private static final String LSP_TYPE_CR = "cr";
@@ -105,9 +107,11 @@
private static final int DELAY_MS = 1100;
private static final double BANDWIDTH_KBPS = 1_000;
private static final double BANDWIDTH_MBPS = 1_000_000;
-
+ private static String[] linkColor = {"pCol1", "pCol2", "pCol3", "pCol4", "pCol5",
+ "pCol6", "pCol7", "pCol8", "pCol9", "pCol10",
+ "pCol11", "pCol12", "pCol13", "pCol14", "pCol15"};
+ private static final int LINK_COLOR_MAX = 15;
private Set<Link> allPathLinks;
- private int highlightDelay;
private ElementId src, dst;
private List<Path> paths = new LinkedList<>();
private int pathIndex;
@@ -141,6 +145,7 @@
new UpdatePathHandler(),
new RemovePathQueryHandler(),
new RemovePathHandler(),
+ new UpdatePathInfoHandler(),
new ShowTunnelHandler());
}
@@ -276,6 +281,50 @@
}
/**
+ * Handles the 'update path' event received from the client.
+ */
+ private final class UpdatePathInfoHandler extends RequestHandler {
+
+ public UpdatePathInfoHandler() {
+ super(PCEWEB_TUNNEL_UPDATE_INFO);
+ }
+
+ @Override
+ public void process(long sid, ObjectNode payload) {
+ String tunnelIdStr = string(payload, TUNNEL_ID);
+
+ if (tunnelIdStr == null) {
+ log.error("PCE update path is failed.");
+ }
+
+ if (tunnelIdStr.equals(STRING_NULL)) {
+ log.error("PCE update path is failed.");
+ return;
+ }
+
+ if (pceService == null) {
+ log.error("PCE service is not active");
+ return;
+ }
+
+ TunnelId tunnelId = TunnelId.valueOf(tunnelIdStr);
+ Tunnel tunnel = tunnelService.queryTunnel(tunnelId);
+ ObjectNode result = objectNode();
+ ArrayNode arrayNode = arrayNode();
+
+ arrayNode.add("Tunnel");
+ arrayNode.add(tunnelIdStr);
+ arrayNode.add("BandWidth");
+ arrayNode.add(tunnel.annotations().value("bandwidth"));
+ arrayNode.add("CostType");
+ arrayNode.add(tunnel.annotations().value("costType"));
+
+ result.putArray(BUFFER_ARRAY).addAll(arrayNode);
+ sendMessage(PCEWEB_TUNNEL_UPDATE_INFO_REPLY, sid, result);
+ }
+ }
+
+ /**
* Handles the 'remove path query' event received from the client.
*/
private final class RemovePathQueryHandler extends RequestHandler {
@@ -484,7 +533,7 @@
}
if (bandWidthType.equals(BANDWIDTH_TYPE_KBPS)) {
bwValue = bwValue * BANDWIDTH_KBPS;
- } else {
+ } else if (bandWidthType.equals(BANDWIDTH_TYPE_MBPS)) {
bwValue = bwValue * BANDWIDTH_MBPS;
}
@@ -516,20 +565,20 @@
* Handles the highlights of selected path.
*/
private void hilightAndSendPaths(Highlights highlights) {
- PceWebLinkMap linkMap = new PceWebLinkMap();
- allPathLinks.forEach(linkMap::add);
- Set<Link> selectedPathLinks;
-
- selectedPathLinks = paths.isEmpty() ?
- ImmutableSet.of() : ImmutableSet.copyOf(paths.get(pathIndex).links());
-
- if (highlightDelay > 0) {
- highlights.delay(highlightDelay);
+ LinkHighlight lh;
+ int linkclr = 0;
+ for (Path path : paths) {
+ for (Link link : path.links()) {
+ lh = new LinkHighlight(TopoUtils.compactLinkString(link), PRIMARY_HIGHLIGHT)
+ .addMod(new Mod(linkColor[linkclr]));
+ highlights.add(lh);
+ }
+ linkclr = linkclr + 1;
+ if (linkclr == LINK_COLOR_MAX) {
+ linkclr = 0;
+ }
}
- for (PceWebLink plink : linkMap.biLinks()) {
- plink.computeHilight(selectedPathLinks, allPathLinks);
- highlights.add(plink.highlight(null));
- }
+
sendMessage(TopoJson.highlightsMessage(highlights));
}
@@ -578,9 +627,7 @@
private class InternalTopologyListener implements TopologyListener {
@Override
public void event(TopologyEvent event) {
- highlightDelay = DELAY_MS;
findTunnelAndHighlights();
- highlightDelay = 0;
}
}
@@ -592,9 +639,7 @@
public void event(TunnelEvent event) {
Tunnel tunnel = event.subject();
if (tunnel.type() == MPLS) {
- highlightDelay = DELAY_MS;
findTunnelAndHighlights();
- highlightDelay = 0;
}
}
}
@@ -604,17 +649,19 @@
*/
private void findTunnelAndHighlights() {
Collection<Tunnel> tunnelSet = null;
+ Highlights highlights = new Highlights();
+ paths.removeAll(paths);
tunnelSet = tunnelService.queryTunnel(MPLS);
if (tunnelSet.size() == 0) {
log.warn("Tunnel does not exist");
+ sendMessage(TopoJson.highlightsMessage(highlights));
return;
}
- paths.removeAll(paths);
- Highlights highlights = new Highlights();
for (Tunnel tunnel : tunnelSet) {
if (tunnel.path() == null) {
log.error("path does not exist");
+ sendMessage(TopoJson.highlightsMessage(highlights));
return;
}
Link firstLink = tunnel.path().links().get(0);
diff --git a/apps/pce/pceweb/src/main/resources/app/view/pcewebTopov/pcewebTopov.css b/apps/pce/pceweb/src/main/resources/app/view/pcewebTopov/pcewebTopov.css
index 705f891..8e414c0 100644
--- a/apps/pce/pceweb/src/main/resources/app/view/pcewebTopov/pcewebTopov.css
+++ b/apps/pce/pceweb/src/main/resources/app/view/pcewebTopov/pcewebTopov.css
@@ -2,3 +2,153 @@
.radioButtonSpace {
margin-left:20px;
}
+/* color:1 */
+#ov-topo svg .link.primary.pCol1 {
+ stroke-width: 6px;
+}
+.light #ov-topo svg .link.primary.pCol1 {
+ stroke: #FF00CE;
+}
+.dark #ov-topo svg .link.primary.pCol1 {
+ stroke: #FF00CE;
+}
+/* color:2 */
+#ov-topo svg .link.primary.pCol2 {
+ stroke-width: 6px;
+}
+.light #ov-topo svg .link.primary.pCol2 {
+ stroke: #ff4000;
+}
+.dark #ov-topo svg .link.primary.pCol2 {
+ stroke: #ff4000;
+}
+/* color:3 */
+#ov-topo svg .link.primary.pCol3 {
+ stroke-width: 6px;
+}
+.light #ov-topo svg .link.primary.pCol3 {
+ stroke: #ffb400;
+}
+.dark #ov-topo svg .link.primary.pCol3 {
+ stroke: #ffb400;
+}
+/* color:4 */
+#ov-topo svg .link.primary.pCol4 {
+ stroke-width: 6px;
+}
+.light #ov-topo svg .link.primary.pCol4 {
+ stroke: #89ff00;
+}
+.dark #ov-topo svg .link.primary.pCol4 {
+ stroke: #89ff00;
+}
+/* color:5 */
+#ov-topo svg .link.primary.pCol5 {
+ stroke-width: 6px;
+}
+.light #ov-topo svg .link.primary.pCol5 {
+ stroke: #00FF2B;
+}
+.dark #ov-topo svg .link.primary.pCol5 {
+ stroke: #00FF2B;
+}
+/* color:6 */
+#ov-topo svg .link.primary.pCol6 {
+ stroke-width: 6px;
+}
+.light #ov-topo svg .link.primary.pCol6 {
+ stroke: #00ffec;
+}
+.dark #ov-topo svg .link.primary.pCol6 {
+ stroke: #00ffec;
+}
+/* color:7 */
+#ov-topo svg .link.primary.pCol7 {
+ stroke-width: 6px;
+}
+.light #ov-topo svg .link.primary.pCol7 {
+ stroke: #00abff;
+}
+.dark #ov-topo svg .link.primary.pCol7 {
+ stroke: #00abff;
+}
+/* color:8 */
+#ov-topo svg .link.primary.pCol8 {
+ stroke-width: 6px;
+}
+.light #ov-topo svg .link.primary.pCol8 {
+ stroke: #005eff;
+}
+.dark #ov-topo svg .link.primary.pCol8 {
+ stroke: #005eff;
+}
+/* color:9 */
+#ov-topo svg .link.primary.pCol9 {
+ stroke-width: 6px;
+}
+.light #ov-topo svg .link.primary.pCol9 {
+ stroke: #0011ff;
+}
+.dark #ov-topo svg .link.primary.pCol9 {
+ stroke: #0011ff;
+}
+/* color:10 */
+#ov-topo svg .link.primary.pCol10 {
+ stroke-width: 6px;
+}
+.light #ov-topo svg .link.primary.pCol10 {
+ stroke: #7c00ff;
+}
+.dark #ov-topo svg .link.primary.pCol10 {
+ stroke: #7c00ff;
+}
+/* color:11 */
+#ov-topo svg .link.primary.pCol11 {
+ stroke-width: 6px;
+}
+.light #ov-topo svg .link.primary.pCol11 {
+ stroke: #ffe700;
+}
+.dark #ov-topo svg .link.primary.pCol11 {
+ stroke: #ffe700;
+}
+/* color:12 */
+#ov-topo svg .link.primary.pCol12 {
+ stroke-width: 6px;
+}
+.light #ov-topo svg .link.primary.pCol12 {
+ stroke: #00ffec;
+}
+.dark #ov-topo svg .link.primary.pCol12 {
+ stroke: #00ffec;
+}
+/* color:13 */
+#ov-topo svg .link.primary.pCol13 {
+ stroke-width: 6px;
+}
+.light #ov-topo svg .link.primary.pCol13 {
+ stroke: #c900ff;
+}
+.dark #ov-topo svg .link.primary.pCol13 {
+ stroke: #c900ff;
+}
+/* color:14 */
+#ov-topo svg .link.primary.pCol14 {
+ stroke-width: 6px;
+}
+.light #ov-topo svg .link.primary.pCol14 {
+ stroke: #ff00e7;
+}
+.dark #ov-topo svg .link.primary.pCol14 {
+ stroke: #ff00e7;
+}
+/* color:15 */
+#ov-topo svg .link.primary.pCol15 {
+ stroke-width: 6px;
+}
+.light #ov-topo svg .link.primary.pCol15 {
+ stroke: #3c00ff;
+}
+.dark #ov-topo svg .link.primary.pCol15 {
+ stroke: #3c00ff;
+}
diff --git a/apps/pce/pceweb/src/main/resources/app/view/pcewebTopov/pcewebTopovDemo.js b/apps/pce/pceweb/src/main/resources/app/view/pcewebTopov/pcewebTopovDemo.js
index bf7723d..06d6771 100644
--- a/apps/pce/pceweb/src/main/resources/app/view/pcewebTopov/pcewebTopovDemo.js
+++ b/apps/pce/pceweb/src/main/resources/app/view/pcewebTopov/pcewebTopovDemo.js
@@ -21,7 +21,7 @@
// injected refs
var $log, fs, flash, wss, tps, ns, tds, ds;
- var tunnelNameData, tunnelNameDataRemove;
+ var tunnelNameData, tunnelNameDataRemove, tunnelDataUpdateInfo, tunnelIdUpd;
// constants
var srcMessage = 'pceTopovSetSrc',
dstMessage = 'pceTopovSetDst',
@@ -30,14 +30,17 @@
updatePathmsgQuery = 'pceTopovUpdateQuery',
remPathmsgQuery = 'pceTopovRemQuery',
updatePathmsg = 'pceTopovUpdate',
+ updatePathmsgInfo = 'updatePathmsgInfo',
remPathmsg = 'pceTopovRem',
showTunnelInfoMsg = 'pceTopovShowTunnels',
queryDisplayTunnelMsg = 'pceTopovTunnelDisplay',
- showTunnelInfoRemoveMsg = 'pceTopovShowTunnelsRem';
+ showTunnelInfoRemoveMsg = 'pceTopovShowTunnelsRem',
+ showTunnelInfoUpdateMsg = 'pceTopovShowTunnelsUpdate';
// internal state
var currentMode = null;
var handlerMap = {},
- handlerMapRem = {};
+ handlerMapRem = {},
+ handlerMapShowUpdate = {};
// === ---------------------------
// === Helper functions
@@ -89,8 +92,6 @@
id: id
});
}
-
-
p.append('span').text(nameField);
p.append('br');
}
@@ -100,6 +101,7 @@
addAttribute('band-width-value-name', 'band-width-value', null, 'number');
addAttribute('pce-band-type', 'band-kpbs-val', 'kbps', 'radio');
addAttribute('pce-band-type', 'band-mpbs-val', 'mbps', 'radio');
+ addAttribute('pce-band-type', 'band-bps-val', 'bps', 'radio');
//Add the cost type related inputs.
addAttribute('pce-cost-type-name', 'pce-cost-type', 'Cost Type', 'checkbox');
addAttribute('pce-cost-type-valname', 'pce-cost-type-igp', 'IGP', 'radio');
@@ -139,10 +141,11 @@
return content;
}
- function createUserTextUpdatePathEvent() {
+ function createUserTextUpdatePathEvent(data) {
var content = ds.createDiv(),
form = content.append('form'),
p = form.append('p');
+ var constType;
function addAttribute(name, id, nameField, type) {
if (type == 'radio') {
@@ -165,15 +168,79 @@
p.append('br');
}
- //Add the bandwidth related inputs.
- addAttribute('band-width-name', 'update-band-width-box', 'Band Width', 'checkbox');
- addAttribute('band-width-value-name', 'update-band-width-value', null, 'number');
- addAttribute('pce-band-type', 'update-band-kpbs-val', 'kbps', 'radio');
- addAttribute('pce-band-type', 'update-band-mpbs-val', 'mbps', 'radio');
- //Add the cost type related inputs.
- addAttribute('pce-cost-type', 'update-pce-cost-type', 'Cost Type', 'checkbox');
- addAttribute('pce-cost-type-value', 'update-pce-cost-type-igp', 'IGP', 'radio');
- addAttribute('pce-cost-type-value', 'update-pce-cost-type-te', 'TE', 'radio');
+ data.a.forEach( function (val, idx) {
+ if (val == 'Tunnel') {
+ constType = 'TUNNEL';
+ return;
+ }
+
+ if (val == 'BandWidth') {
+ constType = 'BW';
+ return;
+ }
+
+ if (val == 'CostType') {
+ constType = 'CT';
+ return;
+ }
+
+ if (constType == 'TUNNEL') {
+ p.append('span').text('Tunnel Id: ');
+ p.append('span').text(val);
+ p.append('br');
+ tunnelIdUpd = val;
+ }
+
+ if (constType == 'BW') {
+ addAttribute('band-width-name', 'update-band-width-box', 'Band Width', 'checkbox');
+ p.append('input').attr({
+ id: 'update-band-width-value',
+ type: 'number',
+ name: 'band-width-value-name',
+ value: val
+ });
+ p.append('br');
+ p.append('input').attr({
+ id: 'update-band-bps-val',
+ type: 'radio',
+ name: 'pce-band-type',
+ checked: 'checked',
+ class: 'radioButtonSpace'
+ });
+ p.append('span').text('bps');
+ p.append('br');
+ addAttribute('pce-band-type', 'update-band-kbps-val', 'kbps', 'radio');
+ addAttribute('pce-band-type', 'update-band-mbps-val', 'mbps', 'radio');
+ }
+
+ if (constType == 'CT') {
+ addAttribute('pce-cost-type', 'update-pce-cost-type', 'Cost Type', 'checkbox');
+ if (val == 'COST') {
+ p.append('input').attr({
+ id: 'update-pce-cost-type-igp',
+ type: 'radio',
+ name: 'pce-cost-type-value',
+ checked: 'checked',
+ class: 'radioButtonSpace'
+ });
+ p.append('span').text('IGP');
+ p.append('br');
+ addAttribute('pce-cost-type-value', 'update-pce-cost-type-te', 'TE', 'radio');
+
+ } else {
+ addAttribute('pce-cost-type-value', 'update-pce-cost-type-igp', 'IGP', 'radio');
+ p.append('input').attr({
+ id: 'update-pce-cost-type-te',
+ type: 'radio',
+ name: 'pce-cost-type-value',
+ checked: 'checked',
+ class: 'radioButtonSpace'
+ });
+ p.append('span').text('TE');
+ p.append('br');
+ }
+ }
+ } );
return content;
}
@@ -222,66 +289,65 @@
tdString = val;
}
} );
+ //send event to server for getting the tunnel information.
+ if (tdString != null) {
+ handlerMapShowUpdate[showTunnelInfoUpdateMsg] = showTunnelInfoUpdateMsgHandle;
+ wss.bindHandlers(handlerMapShowUpdate);
- constraintsUpdateDialog(tdString);
+ wss.sendEvent(updatePathmsgInfo, {
+ tunnelid: tdString
+ });
+ }
+ //constraintsUpdateDialog(tdString);
$log.debug('Dialog OK button clicked');
}
tds.openDialog()
.setTitle('Available LSPs with selected device')
.addContent(createUserTextUpdate(data))
- .addOkChained(dOkUpdate, 'OK')
+ .addOk(dOkUpdate, 'OK')
.addCancel(dClose, 'Close')
.bindKeys();
}
- function constraintsUpdateDialog(tunnelId) {
+ function dOkUpdateEvent() {
+ $log.debug('Select constraints for update path Dialog OK button pressed');
- // invoked when the OK button is pressed on this dialog
- function dOkUpdateEvent() {
- $log.debug('Select constraints for update path Dialog OK button pressed');
+ var bandWidth = isChecked('update-band-width-box'),
+ bandValue = null,
+ bandType = null;
- var bandWidth = isChecked('update-band-width-box'),
- bandValue = null,
- bandType = null;
+ if (bandWidth) {
+ bandValue = getCheckedValue('update-band-width-value');
- if (bandWidth) {
- bandValue = d3.select('#update-band-width-value');
-
- if (isChecked('update-band-kpbs-val')) {
+ if (isChecked('update-band-kbps-val')) {
bandType = 'kbps';
- } else if (isChecked('update-band-mpbs-val')) {
+ } else if (isChecked('update-band-mbps-val')) {
bandType = 'mbps';
- }
+ } else if (isChecked('update-band-bps-val')) {
+ bandType = 'bps';
}
-
- var costType = isChecked('update-pce-cost-type'),
- costTypeVal = null;
-
- if (costType) {
- if (isChecked('update-pce-cost-type-igp')) {
- costTypeVal = 'igp';
- } else if (isChecked('update-pce-cost-type-te')) {
- costTypeVal = 'te';
- }
- }
-
- wss.sendEvent(updatePathmsg, {
- bw: bandValue,
- ctype: costTypeVal,
- tunnelname: tunnelId
- });
-
- flash.flash('update path message');
-
}
- tds.openDialog()
- .setTitle('Select constraints for update path')
- .addContent(createUserTextUpdatePathEvent())
- .addCancel()
- .addOk(dOkUpdateEvent, 'OK') // NOTE: NOT the "chained" version!
- .bindKeys();
+ var costType = isChecked('update-pce-cost-type'),
+ costTypeVal = null;
+
+ if (costType) {
+ if (isChecked('update-pce-cost-type-igp')) {
+ costTypeVal = 'igp';
+ } else if (isChecked('update-pce-cost-type-te')) {
+ costTypeVal = 'te';
+ }
+ }
+
+ wss.sendEvent(updatePathmsg, {
+ bw: bandValue,
+ bwtype: bandType,
+ ctype: costTypeVal,
+ tunnelname: tunnelIdUpd
+ });
+
+ flash.flash('update path message');
}
@@ -297,6 +363,18 @@
.bindKeys();
}
+ function showTunnelInfoUpdateMsgHandle(data) {
+
+ wss.unbindHandlers(handlerMapShowUpdate);
+ tunnelDataUpdateInfo = data;
+ tds.openDialog()
+ .setTitle('Constrainst selection for update')
+ .addContent(createUserTextUpdatePathEvent(data))
+ .addOk(dOkUpdateEvent, 'OK')
+ .addCancel(dClose, 'Close')
+ .bindKeys();
+ }
+
//setup path
function setMode(node) {
@@ -312,6 +390,8 @@
bandType = 'kbps';
} else if (isChecked('band-mpbs-val')) {
bandType = 'mbps';
+ } else if (isChecked('band-bps-val')) {
+ bandType = 'bps';
}
}