aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoInst.js
diff options
context:
space:
mode:
Diffstat (limited to 'framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoInst.js')
-rw-r--r--framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoInst.js373
1 files changed, 373 insertions, 0 deletions
diff --git a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoInst.js b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoInst.js
new file mode 100644
index 00000000..7e929977
--- /dev/null
+++ b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoInst.js
@@ -0,0 +1,373 @@
+/*
+ * 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.
+ */
+
+/*
+ ONOS GUI -- Topology Instances Module.
+ Defines modeling of ONOS instances.
+ */
+
+(function () {
+ 'use strict';
+
+ // injected refs
+ var $log, ps, sus, gs, ts, fs, flash;
+
+ // api from topo
+ var api;
+ /*
+ showMastership( id )
+ */
+
+ // configuration
+ var instCfg = {
+ rectPad: 8,
+ nodeOx: 9,
+ nodeOy: 9,
+ nodeDim: 40,
+ birdOx: 19,
+ birdOy: 21,
+ birdDim: 21,
+ uiDy: 45,
+ titleDy: 30,
+ textYOff: 20,
+ textYSpc: 15
+ },
+ showLogicErrors = true,
+ idIns = 'topo-p-instance',
+ instOpts = {
+ edge: 'left',
+ width: 20
+ };
+
+ // internal state
+ var onosInstances,
+ onosOrder,
+ oiShowMaster,
+ oiBox,
+ themeListener;
+
+
+ // ==========================
+
+ function addInstance(data) {
+ var id = data.id;
+
+ if (onosInstances[id]) {
+ updateInstance(data);
+ return;
+ }
+ onosInstances[id] = data;
+ onosOrder.push(data);
+ updateInstances();
+ }
+
+ function updateInstance(data) {
+ var id = data.id,
+ d = onosInstances[id];
+ if (d) {
+ angular.extend(d, data);
+ updateInstances();
+ } else {
+ logicError('updateInstance: lookup fail: ID = "' + id + '"');
+ }
+ }
+
+ function removeInstance(data) {
+ var id = data.id,
+ d = onosInstances[id];
+ if (d) {
+ var idx = fs.find(id, onosOrder);
+ if (idx >= 0) {
+ onosOrder.splice(idx, 1);
+ }
+ delete onosInstances[id];
+ updateInstances();
+ } else {
+ logicError('removeInstance lookup fail. ID = "' + id + '"');
+ }
+ }
+
+ // ==========================
+
+ function computeDim(self) {
+ var css = window.getComputedStyle(self);
+ return {
+ w: sus.stripPx(css.width),
+ h: sus.stripPx(css.height)
+ };
+ }
+
+ function clickInst(d) {
+ var el = d3.select(this),
+ aff = el.classed('affinity');
+ if (!aff) {
+ setAffinity(el, d);
+ } else {
+ cancelAffinity();
+ }
+ }
+
+ function setAffinity(el, d) {
+ d3.selectAll('.onosInst')
+ .classed('mastership', true)
+ .classed('affinity', false);
+ el.classed('affinity', true);
+
+ // suppress all elements except nodes whose master is this instance
+ api.showMastership(d.id);
+ oiShowMaster = true;
+ }
+
+ function cancelAffinity() {
+ d3.selectAll('.onosInst')
+ .classed('mastership affinity', false);
+
+ api.showMastership(null);
+ oiShowMaster = false;
+ }
+
+ function instRectAttr(dim) {
+ var pad = instCfg.rectPad;
+ return {
+ x: pad,
+ y: pad,
+ width: dim.w - pad*2,
+ height: dim.h - pad*2,
+ rx: 6
+ };
+ }
+
+ function viewBox(dim) {
+ return '0 0 ' + dim.w + ' ' + dim.h;
+ }
+
+ function attachUiBadge(svg) {
+ gs.addGlyph(svg, 'uiAttached', 30, true, [12, instCfg.uiDy])
+ .classed('badgeIcon uiBadge', true);
+ }
+
+ function instColor(id, online) {
+ return sus.cat7().getColor(id, !online, ts.theme());
+ }
+
+ // ==============================
+
+ function updateInstances() {
+ var onoses = oiBox.el().selectAll('.onosInst')
+ .data(onosOrder, function (d) { return d.id; }),
+ instDim = {w:0,h:0},
+ c = instCfg;
+
+ function nSw(n) {
+ return '# Switches: ' + n;
+ }
+
+ // operate on existing onos instances if necessary
+ onoses.each(function (d) {
+ var el = d3.select(this),
+ svg = el.select('svg');
+ instDim = computeDim(this);
+
+ // update online state
+ el.classed('online', d.online);
+
+ // update ui-attached state
+ svg.select('use.uiBadge').remove();
+ if (d.uiAttached) {
+ attachUiBadge(svg);
+ }
+
+ function updAttr(id, value) {
+ svg.select('text.instLabel.'+id).text(value);
+ }
+
+ updAttr('ip', d.ip);
+ updAttr('ns', nSw(d.switches));
+ });
+
+
+ // operate on new onos instances
+ var entering = onoses.enter()
+ .append('div')
+ .attr('class', 'onosInst')
+ .classed('online', function (d) { return d.online; })
+ .on('click', clickInst);
+
+ entering.each(function (d) {
+ var el = d3.select(this),
+ rectAttr,
+ svg;
+ instDim = computeDim(this);
+ rectAttr = instRectAttr(instDim);
+
+ svg = el.append('svg').attr({
+ width: instDim.w,
+ height: instDim.h,
+ viewBox: viewBox(instDim)
+ });
+
+ svg.append('rect').attr(rectAttr);
+
+ gs.addGlyph(svg, 'bird', 28, true, [14, 14])
+ .classed('badgeIcon', true);
+
+ if (d.uiAttached) {
+ attachUiBadge(svg);
+ }
+
+ var left = c.nodeOx + c.nodeDim,
+ len = rectAttr.width - left,
+ hlen = len / 2,
+ midline = hlen + left;
+
+ // title
+ svg.append('text')
+ .attr({
+ class: 'instTitle',
+ x: midline,
+ y: c.titleDy
+ })
+ .text(d.id);
+
+ // a couple of attributes
+ var ty = c.titleDy + c.textYOff;
+
+ function addAttr(id, label) {
+ svg.append('text').attr({
+ class: 'instLabel ' + id,
+ x: midline,
+ y: ty
+ }).text(label);
+ ty += c.textYSpc;
+ }
+
+ addAttr('ip', d.ip);
+ addAttr('ns', nSw(d.switches));
+ });
+
+ // operate on existing + new onoses here
+ // set the affinity colors...
+ onoses.each(function (d) {
+ var el = d3.select(this),
+ rect = el.select('svg').select('rect'),
+ col = instColor(d.id, d.online);
+ rect.style('fill', col);
+ });
+
+ // adjust the panel size appropriately...
+ oiBox.width(instDim.w * onosOrder.length);
+ oiBox.height(instDim.h);
+
+ // remove any outgoing instances
+ onoses.exit().remove();
+ }
+
+
+ // ==========================
+
+ function logicError(msg) {
+ if (showLogicErrors) {
+ $log.warn('TopoInstService: ' + msg);
+ }
+ }
+
+ function initInst(_api_) {
+ api = _api_;
+ oiBox = ps.createPanel(idIns, instOpts);
+ oiBox.show();
+
+ onosInstances = {};
+ onosOrder = [];
+ oiShowMaster = false;
+
+ // we want to update the instances, each time the theme changes
+ themeListener = ts.addListener(updateInstances);
+ }
+
+ function destroyInst() {
+ ts.removeListener(themeListener);
+ themeListener = null;
+
+ ps.destroyPanel(idIns);
+ oiBox = null;
+
+ onosInstances = {};
+ onosOrder = [];
+ oiShowMaster = false;
+ }
+
+ function showInsts() {
+ oiBox.show();
+ }
+
+ function hideInsts() {
+ oiBox.hide();
+ }
+
+ function toggleInsts(x) {
+ var kev = (x === 'keyev'),
+ on,
+ verb;
+
+ if (kev) {
+ on = oiBox.toggle();
+ } else {
+ on = !!x;
+ if (on) {
+ showInsts();
+ } else {
+ hideInsts();
+ }
+ }
+ verb = on ? 'Show' : 'Hide';
+ flash.flash(verb + ' instances panel');
+ return on;
+ }
+
+ // ==========================
+
+ angular.module('ovTopo')
+ .factory('TopoInstService',
+ ['$log', 'PanelService', 'SvgUtilService', 'GlyphService',
+ 'ThemeService', 'FnService', 'FlashService',
+
+ function (_$log_, _ps_, _sus_, _gs_, _ts_, _fs_, _flash_) {
+ $log = _$log_;
+ ps = _ps_;
+ sus = _sus_;
+ gs = _gs_;
+ ts = _ts_;
+ fs = _fs_;
+ flash = _flash_;
+
+ return {
+ initInst: initInst,
+ destroyInst: destroyInst,
+
+ addInstance: addInstance,
+ updateInstance: updateInstance,
+ removeInstance: removeInstance,
+
+ cancelAffinity: cancelAffinity,
+
+ isVisible: function () { return oiBox.isVisible(); },
+ show: showInsts,
+ hide: hideInsts,
+ toggle: toggleInsts,
+ showMaster: function () { return oiShowMaster; }
+ };
+ }]);
+}());