blob: 11726622578ef77cfd05806181685b895cd10528 [file] [log] [blame]
(function () {
'use strict';
// injected refs
var $log, ps, sus, gs, ts;
// api from topo
var api;
// configuration
var showLogicErrors = true,
idIns = 'topo2-p-instance',
instOpts = {
edge: 'left',
width: 20
};
// internal state
var onosInstances,
onosOrder,
oiBox;
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 clickInst(d) {
var el = d3.select(this),
aff = el.classed('affinity');
if (aff) {
cancelAffinity();
} else {
setAffinity(el, d);
}
}
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);
}
function cancelAffinity() {
d3.selectAll('.onosInst')
.classed('mastership affinity', false);
api.showMastership(null);
}
function attachUiBadge(svg) {
gs.addGlyph(svg, 'uiAttached', 24, true, [14, 54])
.classed('badgeIcon uiBadge', true);
}
function attachReadyBadge(svg) {
gs.addGlyph(svg, 'checkMark', 16, true, [18, 40])
.classed('badgeIcon readyBadge', true);
}
function instColor(id, online) {
return sus.cat7().getColor(id, !online, ts.theme());
}
// ==============================
function updateInstances() {
var rox = 5,
roy = 5,
rw = 160,
rhh = 30,
rbh = 45,
tx = 48,
instSvg = {
width: 170,
height: 85,
viewBox: '0 0 170 85'
},
headRect = {
x: rox,
y: roy,
width: rw,
height: rhh
},
bodyRect = {
x: rox,
y: roy + rhh,
width: rw,
height: rbh
},
titleAttr = {
class: 'instTitle',
x: tx,
y: 27
};
var onoses = oiBox.el().selectAll('.onosInst')
.data(onosOrder, function (d) { return d.id; });
function nSw(n) {
return 'Devices: ' + n;
}
// operate on existing onos instances if necessary
onoses.each(function (d) {
var el = d3.select(this),
svg = el.select('svg');
// update online state
el.classed('online', d.online);
el.classed('ready', d.ready);
// 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')
.classed('onosInst', true)
.classed('online', function (d) { return d.online; })
.classed('ready', function (d) { return d.ready; })
.on('click', clickInst);
entering.each(function (d) {
var el = d3.select(this),
svg = el.append('svg').attr(instSvg);
svg.append('rect').attr(headRect);
svg.append('rect').attr(bodyRect);
gs.addGlyph(svg, 'bird', 20, false, [15, 10])
.classed('badgeIcon bird', true);
attachReadyBadge(svg);
if (d.uiAttached) {
attachUiBadge(svg);
}
svg.append('text')
.attr(titleAttr)
.text(d.id);
var ty = 55;
function addAttr(id, label) {
svg.append('text').attr({
class: 'instLabel ' + id,
x: tx,
y: ty
}).text(label);
ty += 18;
}
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(instSvg.width * onosOrder.length);
oiBox.height(instSvg.height);
// 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 = [];
// we want to update the instances, each time the theme changes
ts.addListener(updateInstances);
}
function allInstances(data) {
$log.debug('Update all instances', data);
var members = data.members;
members.forEach(function (member) {
addInstance(member);
});
}
function destroy() {
ts.removeListener(updateInstances);
ps.destroyPanel(idIns);
oiBox = null;
onosInstances = {};
onosOrder = [];
}
angular.module('ovTopo2')
.factory('Topo2InstanceService',
['$log', 'PanelService', 'SvgUtilService', 'GlyphService',
'ThemeService',
function (_$log_, _ps_, _sus_, _gs_, _ts_) {
$log = _$log_;
ps = _ps_;
sus = _sus_;
gs = _gs_;
ts = _ts_;
return {
initInst: initInst,
allInstances: allInstances,
destroy: destroy
};
}]);
})();