Mahesh Raju-Huawei
Committed by Gerrit Code Review

[ONOS-4159] PCE Web GUI implementation: Tunnel highlight and defect fixes

Change-Id: I385c00d4654e746133f0d9757511e3a8821fad7a
......@@ -36,8 +36,11 @@ import org.onosproject.ui.UiConnection;
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.TunnelEvent;
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 @@ import java.util.Set;
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 @@ public class PceWebTopovMessageHandler extends UiMessageHandler {
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 @@ public class PceWebTopovMessageHandler extends UiMessageHandler {
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 @@ public class PceWebTopovMessageHandler extends UiMessageHandler {
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 @@ public class PceWebTopovMessageHandler extends UiMessageHandler {
new UpdatePathHandler(),
new RemovePathQueryHandler(),
new RemovePathHandler(),
new UpdatePathInfoHandler(),
new ShowTunnelHandler());
}
......@@ -276,6 +281,50 @@ public class PceWebTopovMessageHandler extends UiMessageHandler {
}
/**
* 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 @@ public class PceWebTopovMessageHandler extends UiMessageHandler {
}
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 @@ public class PceWebTopovMessageHandler extends UiMessageHandler {
* 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);
}
for (PceWebLink plink : linkMap.biLinks()) {
plink.computeHilight(selectedPathLinks, allPathLinks);
highlights.add(plink.highlight(null));
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;
}
}
sendMessage(TopoJson.highlightsMessage(highlights));
}
......@@ -578,9 +627,7 @@ public class PceWebTopovMessageHandler extends UiMessageHandler {
private class InternalTopologyListener implements TopologyListener {
@Override
public void event(TopologyEvent event) {
highlightDelay = DELAY_MS;
findTunnelAndHighlights();
highlightDelay = 0;
}
}
......@@ -592,9 +639,7 @@ public class PceWebTopovMessageHandler extends UiMessageHandler {
public void event(TunnelEvent event) {
Tunnel tunnel = event.subject();
if (tunnel.type() == MPLS) {
highlightDelay = DELAY_MS;
findTunnelAndHighlights();
highlightDelay = 0;
}
}
}
......@@ -604,17 +649,19 @@ public class PceWebTopovMessageHandler extends UiMessageHandler {
*/
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);
......
......@@ -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;
}
......
......@@ -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) {
// invoked when the OK button is pressed on this dialog
function dOkUpdateEvent() {
$log.debug('Select constraints for update path Dialog OK button pressed');
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 = d3.select('#update-band-width-value');
if (bandWidth) {
bandValue = getCheckedValue('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;
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';
}
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();
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';
}
}
......