blob: a424249213df9e485c05eb0d5e5138b5b8d42a55 [file] [log] [blame]
/*
* Copyright 2016-present Open Networking Foundation
*
* 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.
*/
/*
ONOS GUI -- Openstack Telemetry View Module
*/
(function () {
'use strict';
// injected references
var $log, $scope, $location, ks, fs, cbs, ns, tov, ots, wss, tts, api, gs, ps, ds;
// constants
var pCls = 'topo-p',
idTelemetry = 'topo-p-telemetry',
idTelemetryDiag = 'telemetry-dialog',
telemetryPanelOpts = {
edge: 'left',
width: 330, // telemetry panel width
}
// panels
var telemetry;
// selected info (by mouse click event)
var selectedItem
// constants
var ostIsActReq = 'openstackFlowStatsIsActivatedRequest',
ostIsActResp = 'openstackFlowStatsIsActivatedResponse',
ostCreateReq = 'openstackFlowStatsCreateRequest',
ostCreateResp = 'openstackFlowStatsCreateResponse';
var topoLion = function (x) {
return '#ttrafov#' + x + '#';
};
var overlay = {
overlayId: 'ostelemetry-overlay',
glyphId: 'm_details',
tooltip: 'Openstack Telemetry Overlay',
activate: function () {
$log.debug("Openstack telemetry topology overlay is ACTIVATED");
},
deactivate: function () {
destroyTelemetryPanel();
$log.debug("Openstack telemetry topology overlay is DEACTIVATED");
},
// detail panel button definitions
buttons: {
createHostTelemetryBtn: {
gid: 'm_details',
tt: 'Create Host-to-Host Telemetry',
cb: displayTelemetry
},
showRelatedTraffic: {
gid: 'm_relatedIntents',
tt: function () { return topoLion('tr_btn_show_related_traffic'); },
cb: function (data) { tts.showRelatedIntents(); },
},
},
hooks: {
multi: function (selectOrder) {
var selectedHost = new Object();
$log.debug("Selected object: ", selectOrder);
for (var index in selectOrder) {
if (index == 0) {
selectedHost.src = selectOrder[index];
$log.debug("Source host: ", selectedHost.src);
} else if (index == 1) {
selectedHost.dst = selectOrder[index];
$log.debug("Destination host: ", selectedHost.dst);
}
}
selectedItem = selectedHost;
tov.addDetailButton('showRelatedTraffic');
if(selectOrder.length == 2) {
tov.addDetailButton('createHostTelemetryBtn');
}
}
}
};
// Panel API
function createTopoPanel(id, opts) {
var p = ps.createPanel(id, opts),
pid = id,
header, body, footer;
p.classed(pCls, true);
function panel() {
return p;
}
function hAppend(x) {
return header.append(x);
}
function bAppend(x) {
return body.append(x);
}
function fAppend(x) {
return footer.append(x);
}
function setup() {
p.empty();
p.append('div').classed('header', true);
p.append('div').classed('body', true);
p.append('div').classed('footer', true);
header = p.el().select('.header');
body = p.el().select('.body');
footer = p.el().select('.footer');
}
function destroy() {
ps.destroyPanel(pid);
}
return {
panel: panel,
setup: setup,
destroy: destroy,
appendHeader: hAppend,
appendBody: bAppend,
appendFooter: fAppend,
};
}
function hideTelemetryPanel() {
telemetry.panel().hide();
}
function destroyTelemetryPanel() {
if(telemetry != null) {
telemetry.destroy();
}
telemetry = null;
}
function addInput(tbody, type, id, label, value) {
var tr = tbody.append('tr'),
lab;
if (typeof label === 'string') {
lab = label.replace(/_/g, ' ');
} else {
lab = label;
}
tr.append('td').attr('class', 'label').text(lab + ' :');
if (type == 'radio') {
var td = tr.append('td');
for(var index in value) {
if(index == 0) {
td.append('input').classed( type + '-input', true)
.attr('type', type)
.attr('value', value[index])
.attr('name', label)
.attr('id', id)
.attr('checked', 'true');
} else {
td.append('input').classed( type + '-input', true)
.attr('type', type)
.attr('name', label)
.attr('id', id)
.attr('value', value[index]);
}
td.append('span').text(value[index]);
}
} else {
tr.append('td').append('input').classed(type + '-input', true).attr('type', type)
.attr('id', id).attr('value', value);
}
}
function addButton(tr, callback, value) {
tr.append('td').append('input').classed('button-input', true).attr('type', 'button')
.attr('value', value).on('click', callback);
}
function makeButton(callback, text, keyName) {
var cb = fs.isF(callback),
key = fs.isS(keyName);
function invoke() {
cb && cb();
}
return createDiv('telemetry-button')
.text(text)
.on('click', invoke);
}
function createDiv(cls) {
var div = d3.select(document.createElement('div'));
if (cls) {
div.classed(cls, true);
}
return div;
}
function displayTelemetry() {
$log.debug("sendEvent openstackFlowStatsIsActivatedRequest: ", selectedItem);
wss.sendEvent(ostIsActReq, selectedItem);
}
function respIsActCb(selected) {
$log.debug("openstackFlowStatsIsActivatedResponse: ", selected);
if(telemetry == null) {
telemetry = createTopoPanel(idTelemetry, telemetryPanelOpts);
}
telemetry.setup();
var svg = telemetry.appendHeader('div')
.classed('icon', true)
.append('svg'),
title = telemetry.appendHeader('h2'),
table = telemetry.appendBody('table'),
tbody = table.append('tbody'),
glyphId = 'm_details';
gs.addGlyph(svg, glyphId, 30, 0, [1, 1]);
title.text('Create Openstack Telemetry');
addInput(tbody, 'text', 'srcIp', 'Source IP', selected.srcName);
addInput(tbody, 'text', 'dstIp', 'Destination IP', selected.dstName);
addInput(tbody, 'radio', 'ipProto', 'Protocol', selected.ipProtoList);
addInput(tbody, 'number', 'srcPort', 'Source Port', "");
addInput(tbody, 'number', 'dstPort', 'Destination Port', "");
telemetry.appendFooter('hr');
var footTr = telemetry.appendFooter('table').append('tbody').append('tr');
addButton(footTr, createTelemetry, 'Create');
addButton(footTr, hideTelemetryPanel, 'Cancel');
telemetry.panel().show();
}
function createTelemetry() {
var telemetryInfo = {};
telemetryInfo.srcIp = document.getElementById('srcIp').value;
telemetryInfo.dstIp = document.getElementById('dstIp').value;
telemetryInfo.ipProto = document.querySelector('input[name="Protocol"]:checked').value;
telemetryInfo.srcPort = document.getElementById('srcPort').value;
telemetryInfo.dstPort = document.getElementById('dstPort').value;
if(telemetryInfo.srcPort == ""){
telemetryInfo.srcPort = 0;
}
if(telemetryInfo.dstPort == ""){
telemetryInfo.dstPort = 0;
}
$log.debug("Creation request: ", telemetryInfo);
wss.sendEvent(ostCreateReq, telemetryInfo);
hideTelemetryPanel();
}
function respCreateCb(result) {
$log.debug("Creation response: ", result);
function dOK() {
if(result.result == "Failed"){
displayTelemetry(selectedItem);
} else {
destroyTelemetryPanel();
}
}
function createContent(value) {
var content = ds.createDiv();
content.append('p').text(value);
return content;
}
ds.openDialog(idTelemetryDiag, telemetryPanelOpts)
.setTitle("Create Telemetry " + result.result)
.addContent(createContent(result.value))
.addOk(dOK);
}
/*
Variable for Chart View
*/
var hasFlow;
var gFlowId;
var gPeriod;
var labels = new Array(1);
var data = new Array(2);
for (var i = 0; i < 2; i++) {
data[i] = new Array(1);
}
var max;
function ceil(num) {
if (isNaN(num)) {
return 0;
}
var pre = num.toString().length - 1
var pow = Math.pow(10, pre);
return (Math.ceil(num / pow)) * pow;
}
function maxInArray(array) {
var merged = [].concat.apply([], array);
return Math.max.apply(null, merged);
}
/*
Chart View : Controller
*/
angular.module('ovOpenstacktelemetry', ["chart.js"])
.controller('OvOpenstacktelemetryCtrl',
['$log', '$scope', '$location', 'FnService', 'ChartBuilderService', 'NavService',
function (_$log_, _$scope_, _$location_, _fs_, _cbs_, _ns_) {
var params;
$log = _$log_;
$scope = _$scope_;
$location = _$location_;
fs = _fs_;
cbs = _cbs_;
ns = _ns_;
params = $location.search();
if (params.hasOwnProperty('flowOpt')) {
$scope.flowOpt = params['flowOpt'];
hasFlow = true;
} else if (params.hasOwnProperty('periodOpt')) {
$scope.periodOpt = params['periodOpt'];
hasFlow = true;
} else {
hasFlow = false;
}
cbs.buildChart({
scope: $scope,
tag: 'openstacktelemetry',
query: params
});
$scope.$watch('chartData', function () {
if (!fs.isEmptyObject($scope.chartData)) {
$scope.showLoader = false;
var length = $scope.chartData.length;
labels = new Array(length);
for (var i = 0; i < 2; i++) {
data[i] = new Array(length);
}
$scope.chartData.forEach(function (cm, idx) {
data[0][idx] = (cm.curr_acc_packet - cm.prev_acc_packet);
data[1][idx] = (cm.curr_acc_byte - cm.prev_acc_byte);
labels[idx] = cm.label;
});
}
max = maxInArray(data)
$scope.labels = labels;
$scope.data = data;
$scope.options = {
scaleOverride : true,
scaleSteps : 10,
scaleStepWidth : ceil(max) / 10,
scaleStartValue : 0,
scaleFontSize : 16
};
$scope.onClick = function (points, evt) {
var label = labels[points[0]._index];
if (label) {
ns.navTo('openstacktelemetry', { flowOpt: label });
$log.log(label);
}
};
if (!fs.isEmptyObject($scope.annots)) {
$scope.flowIds = JSON.parse($scope.annots.flowIds);
$scope.periodOptions = JSON.parse($scope.annots.periodOptions);
}
$scope.onChange = function (flowId) {
gFlowId = flowId;
ns.navTo('openstacktelemetry', { periodOpt: gPeriod , flowOpt: flowId });
};
$scope.onPeriodChange = function (period) {
gPeriod = period;
ns.navTo('openstacktelemetry', { periodOpt: period , flowOpt: gFlowId });
};
});
$scope.series = ['Current Packet', 'Current Byte'];
$scope.labels = labels;
$scope.data = data;
$scope.chartColors = [
'#286090',
'#F7464A',
'#46BFBD',
'#FDB45C',
'#97BBCD',
'#4D5360',
'#8c4f9f'
];
Chart.defaults.global.colours = $scope.chartColors;
$scope.showLoader = true;
$log.log('OvOpenstacktelemetryCtrl has been created');
}])
// Network Topology View : Factory
.factory('OpenstacktelemetryService',
['$log', 'FnService', 'WebSocketService', 'GlyphService', 'PanelService', 'DialogService',
function (_$log_, _fs_, _wss_, _gs_, _ps_, _ds_) {
$log = _$log_;
fs = _fs_;
wss = _wss_;
gs = _gs_;
ps = _ps_;
ds = _ds_;
var handlers = {},
telemetryOverlay = 'ostelemetry-overlay',
defaultOverlay = 'traffic';
handlers[ostIsActResp] = respIsActCb;
handlers[ostCreateResp] = respCreateCb;
wss.bindHandlers(handlers);
return {
displayTelemetry: displayTelemetry
};
}])
.run(['$log', 'TopoOverlayService', 'OpenstacktelemetryService', 'TopoTrafficService',
function (_$log_, _tov_, _ots_, _tts_) {
$log = _$log_;
tov = _tov_;
ots = _ots_;
tts = _tts_;
tov.register(overlay);
}]
);
}());