blob: a9a76ece6d5bcf3f54d1859f3fb198e5488a8efc [file] [log] [blame]
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you 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.
*/
/**
* @module QDR
*/
/**
* @module QDR
*/
var QDR = (function (QDR) {
/**
* @method OverviewController
* @param $scope
* @param QDRService
* @param QDRChartServer
* dialogServer
* $location
*
* Controller that handles the QDR overview page
*/
QDR.module.controller("QDR.OverviewController", ['$scope', 'QDRService', '$location', 'localStorage', '$timeout', function($scope, QDRService, $location, localStorage, $timeout) {
console.log("QDR.OverviewControll started with location of " + $location.path() + " and connection of " + QDRService.connected);
var columnStateKey = 'QDRColumnKey.';
var OverviewExpandedKey = "QDROverviewExpanded"
var OverviewActivatedKey = "QDROverviewActivated"
// we want attributes to be listed first, so add it at index 0
$scope.subLevelTabs = [{
content: '<i class="icon-list"></i> Attributes',
title: "View the attribute values on your selection",
isValid: function (workspace) { return true; },
href: function () { return "#/" + QDR.pluginName + "/attributes"; },
index: 0
},
{
content: '<i class="icon-leaf"></i> Operations',
title: "Execute operations on your selection",
isValid: function (workspace) { return true; },
href: function () { return "#/" + QDR.pluginName + "/operations"; },
index: 1
}]
$scope.activeTab = $scope.subLevelTabs[0];
$scope.setActive = function (nav) {
$scope.activeTab = nav;
}
$scope.isValid = function (nav) {
return nav.isValid()
}
$scope.isActive = function (nav) {
return nav == $scope.activeTab;
}
$scope.linkFields = []
$scope.link = null;
var currentTimer;
var refreshInterval = 5000
$scope.modes = [
{title: 'Overview', name: 'Overview', right: false}
];
$scope.templates =
[ { name: 'Routers', url: 'routers.html'},
{ name: 'Router', url: 'router.html'},
{ name: 'Addresses', url: 'addresses.html'},
{ name: 'Address', url: 'address.html'},
{ name: 'Links', url: 'links.html'},
{ name: 'Link', url: 'link.html'},
{ name: 'Connections', url: 'connections.html'},
{ name: 'Connection', url: 'connection.html'},
{ name: 'Logs', url: 'logs.html'},
{ name: 'Log', url: 'log.html'}
];
var topLevelChildren = [];
$scope.allRouterSelected = function (row ) {
console.log("row selected" + row)
}
function afterSelectionChange(rowItem, checkAll) {
var nodeId = rowItem.entity.nodeId;
$("#overtree").dynatree("getTree").activateKey(nodeId);
}
$scope.allRouterFields = [];
$scope.allRouterSelections = [];
$scope.allRouters = {
saveKey: 'allRouters',
data: 'allRouterFields',
columnDefs: [
{
field: 'routerId',
saveKey: 'allRouters',
displayName: 'Router'
},
{
field: 'area',
displayName: 'Area'
},
{
field: 'mode',
displayName: 'Mode'
},
{
field: 'connections',
displayName: 'External connections'
},
{
field: 'addrCount',
displayName: 'Address count'
},
{
field: 'linkCount',
displayName: 'Link count'
}
],
enableColumnResize: true,
multiSelect: false,
selectedItems: $scope.allRouterSelections,
afterSelectionChange: function(data) {
if (data.selected) {
var selItem = $scope.allRouterSelections[0]
var nodeId = selItem.nodeId
// activate Routers->nodeId in the tree
$("#overtree").dynatree("getTree").activateKey(nodeId);
}
}
};
// get info for all routers
var allRouterInfo = function () {
var nodeIds = QDRService.nodeIdList()
var expected = Object.keys(nodeIds).length
var received = 0;
var allRouterFields = [];
var gotNodeInfo = function (nodeName, entity, response) {
var results = response.results;
var name = QDRService.nameFromId(nodeName)
var connections = 0;
results.forEach( function (result) {
var role = QDRService.valFor(response.attributeNames, result, "role")
if (role != 'inter-router') {
++connections
}
})
allRouterFields.push({routerId: name, connections: connections, nodeId: nodeName})
++received
if (expected == received) {
allRouterFields.sort ( function (a,b) { return a.routerId < b.routerId ? -1 : a.routerId > b.routerId ? 1 : 0})
// now get each router's node info
QDRService.getMultipleNodeInfo(nodeIds, "router", [], function (nodeIds, entity, responses) {
for(var r in responses) {
var result = responses[r]
var routerId = QDRService.valFor(result.attributeNames, result.results[0], "routerId")
allRouterFields.some( function (connField) {
if (routerId === connField.routerId) {
result.attributeNames.forEach ( function (attrName) {
connField[attrName] = QDRService.valFor(result.attributeNames, result.results[0], attrName)
})
return true
}
return false
})
}
$scope.allRouterFields = allRouterFields
}, nodeIds[0], false)
}
}
nodeIds.forEach ( function (nodeId, i) {
QDRService.getNodeInfo(nodeId, ".connection", ["role"], gotNodeInfo)
})
loadColState($scope.allRouters)
updateRouterTree(nodeIds)
}
$scope.routerFields = []
$scope.routerGrid = {
saveKey: 'routerGrid',
data: 'routerFields',
columnDefs: [
{
field: 'attribute',
displayName: 'Attribute',
saveKey: 'routerGrid',
width: '40%'
},
{
field: 'value',
displayName: 'Value',
width: '40%'
}
],
enableColumnResize: true,
multiSelect: false
}
// get info for a single router
var routerInfo = function (node) {
$scope.router = node
$scope.routerFields = [];
$scope.allRouterFields.some( function (field) {
if (field.routerId === node.data.title) {
Object.keys(field).forEach ( function (key) {
if (key !== '$$hashKey')
$scope.routerFields.push({attribute: key, value: field[key]})
})
return true
}
})
loadColState($scope.routerGrid);
}
$scope.addressesData = []
$scope.selectedAddresses = []
$scope.addressesGrid = {
saveKey: 'addressesGrid',
data: 'addressesData',
columnDefs: [
{
field: 'address',
saveKey: 'addressesGrid',
displayName: 'address'
},
{
field: 'class',
displayName: 'class'
},
{
field: 'phase',
displayName: 'phase',
cellClass: 'grid-align-value'
},
{
field: 'inproc',
displayName: 'in-proc'
},
{
field: 'local',
displayName: 'local',
cellClass: 'grid-align-value'
},
{
field: 'remote',
displayName: 'remote',
cellClass: 'grid-align-value'
},
{
field: 'in',
displayName: 'in',
cellClass: 'grid-align-value'
},
{
field: 'out',
displayName: 'out',
cellClass: 'grid-align-value'
}
],
enableColumnResize: true,
multiSelect: false,
selectedItems: $scope.selectedAddresses,
afterSelectionChange: function(data) {
if (data.selected) {
var selItem = data.entity;
var nodeId = selItem.uid
$("#overtree").dynatree("getTree").activateKey(nodeId);
}
}
};
// get info for all addresses
var allAddressInfo = function () {
var gotAllAddressFields = function ( addressFields ) {
// update the grid's data
addressFields.sort ( function (a,b) { return a.address < b.address ? -1 : a.address > b.address ? 1 : 0})
addressFields[0].title = addressFields[0].address
for (var i=1; i<addressFields.length; ++i) {
if (addressFields[i].address === addressFields[i-1].address) {
addressFields[i-1].title = addressFields[i-1].address + " (" + addressFields[i-1]['class'] + ")"
addressFields[i].title = addressFields[i].address + " (" + addressFields[i]['class'] + ")"
} else
addressFields[i].title = addressFields[i].address
}
$scope.addressesData = addressFields
// repopulate the tree's child nodes
updateAddressTree(addressFields)
}
getAllAddressFields(gotAllAddressFields)
loadColState($scope.addressesGrid);
}
var getAllAddressFields = function (callback) {
var nodeIds = QDRService.nodeIdList()
var addr_class = function (addr) {
if (!addr) return "-"
if (addr[0] == 'M') return "mobile"
if (addr[0] == 'R') return "router"
if (addr[0] == 'A') return "area"
if (addr[0] == 'L') return "local"
if (addr[0] == 'C') return "link-incoming"
if (addr[0] == 'D') return "link-outgoing"
return "unknown: " + addr[0]
}
var addr_text = function (addr) {
if (!addr)
return "-"
if (addr[0] == 'M')
return addr.substring(2)
else
return addr.substring(1)
}
var addr_phase = function (addr) {
if (!addr)
return "-"
if (addr[0] == 'M')
return addr[1]
return ''
}
var identity_clean = function (identity) {
if (!identity)
return "-"
var pos = identity.indexOf('/')
if (pos >= 0)
return identity.substring(pos + 1)
return identity
}
var addressFields = []
QDRService.getMultipleNodeInfo(nodeIds, "router.address", [], function (nodeIds, entity, response) {
response.aggregates.forEach( function (result) {
var prettySum = function (field) {
var fieldIndex = response.attributeNames.indexOf(field)
if (fieldIndex < 0) {
return "-"
}
var val = result[fieldIndex].sum
return QDRService.pretty(val)
}
var uid = QDRService.valFor(response.attributeNames, result, "identity").sum
var identity = identity_clean(uid)
addressFields.push({
address: addr_text(identity),
'class': addr_class(identity),
phase: addr_phase(identity),
inproc: prettySum("inProcess"),
local: prettySum("subscriberCount"),
remote: prettySum("remoteCount"),
'in': prettySum("deliveriesIngress"),
out: prettySum("deliveriesEgress"),
thru: prettySum("deliveriesTransit"),
toproc: prettySum("deliveriesToContainer"),
fromproc:prettySum("deliveriesFromContainer"),
uid: uid
})
})
callback(addressFields)
}, nodeIds[0])
}
var updateLinkGrid = function ( linkFields ) {
$scope.linkFields = linkFields
// if we have a selected link
if ($scope.link) {
// find the selected link in the array of all links
var links = $scope.linkFields.filter(function (link) {
return link.name === $scope.link.data.fields.name;
})
if (links.length > 0) {
// linkInfo() is the function that is called by dynatree when a link is selected
// It is passed a dynatree node. We need to simulate that node type to update the link grid
linkInfo({data: {title: links[0].title, fields: links[0]}})
}
}
}
// get info for a all links
$scope.selectedLinks = []
$scope.linksGrid = {
saveKey: 'linksGrid',
data: 'linkFields',
columnDefs: [
{
field: 'link',
displayName: 'Link',
groupable: false,
saveKey: 'linksGrid',
width: '12%'
},
{
field: 'linkType',
displayName: 'Link type',
groupable: false,
width: '10%'
},
{
field: 'linkDir',
displayName: 'Link dir',
groupable: false,
width: '8%'
},
{
field: 'adminStatus',
displayName: 'Admin status',
groupable: false,
width: '10%'
},
{
field: 'operStatus',
displayName: 'Oper status',
groupable: false,
width: '10%'
},
{
field: 'deliveryCount',
displayName: 'Delivery Count',
groupable: false,
cellClass: 'grid-align-value',
width: '12%'
},
{
field: 'rate',
displayName: 'Rate',
groupable: false,
cellClass: 'grid-align-value',
width: '8%'
},
{
field: 'uncounts',
displayName: 'Outstanding',
groupable: false,
cellClass: 'grid-align-value',
width: '10%'
},
{
field: 'owningAddr',
displayName: 'Address',
groupable: false,
width: '20%'
}
],
enableColumnResize: true,
enableColumnReordering: true,
showColumnMenu: true,
rowTemplate: 'linkRowTemplate.html',
// aggregateTemplate: "linkAggTemplate.html",
multiSelect: false,
selectedItems: $scope.selectedLinks,
afterSelectionChange: function(data) {
if (data.selected) {
var selItem = data.entity;
var nodeId = selItem.uid
$("#overtree").dynatree("getTree").activateKey(nodeId);
}
}
};
$scope.$on('ngGridEventColumns', function (e, columns) {
var saveInfo = columns.map( function (col) {
return [col.width, col.visible]
})
var saveKey = columns[0].colDef.saveKey
if (saveKey)
localStorage.setItem(columnStateKey+saveKey, JSON.stringify(saveInfo));
})
var loadColState = function (grid) {
if (!grid)
return;
var columns = localStorage.getItem(columnStateKey+grid.saveKey);
if (columns) {
var cols = JSON.parse(columns);
cols.forEach( function (col, index) {
grid.columnDefs[index].width = col[0];
grid.columnDefs[index].visible = col[1]
})
}
}
var allLinkInfo = function () {
getAllLinkFields([updateLinkGrid, updateLinkTree])
loadColState($scope.linksGrid);
}
var getAllLinkFields = function (callbacks) {
var nodeIds = QDRService.nodeIdList()
var linkFields = []
var now = Date.now()
var rate = function (response, result) {
var name = QDRService.valFor(response.attributeNames, result, "linkName").sum
var oldname = $scope.linkFields.filter(function (link) {
return link.linkName === name
})
if (oldname.length > 0) {
var elapsed = (now - oldname[0].timestamp) / 1000;
var delivered = QDRService.valFor(response.attributeNames, result, "deliveryCount").sum - oldname[0].rawDeliveryCount
//QDR.log.debug("elapsed " + elapsed + " delivered " + delivered)
return elapsed > 0 ? parseFloat(Math.round((delivered/elapsed) * 100) / 100).toFixed(2) : 0;
} else {
//QDR.log.debug("unable to find old linkName")
return 0
}
}
QDRService.getMultipleNodeInfo(nodeIds, "router.link", [], function (nodeIds, entity, response) {
response.aggregates.forEach( function (result) {
var prettySum = function (field) {
var fieldIndex = response.attributeNames.indexOf(field)
if (fieldIndex < 0) {
return "-"
}
var val = result[fieldIndex].sum
return QDRService.pretty(val)
}
var uncounts = function () {
var und = QDRService.valFor(response.attributeNames, result, "undeliveredCount").sum
var uns = QDRService.valFor(response.attributeNames, result, "unsettledCount").sum
return und + uns
}
var nameIndex = response.attributeNames.indexOf('name')
var linkName = function () {
var details = result[nameIndex].detail
var names = []
details.forEach( function (detail) {
if (detail.node.endsWith(':'))
names.push(detail.node.slice(0, -1))
else
names.push(detail.node)
})
//var namestr = names.join('-')
var namestr = names.length > 0 ? names[0] : ""
return namestr + ':' + QDRService.valFor(response.attributeNames, result, "identity").sum
}
var fixAddress = function () {
var owningAddr = QDRService.valFor(response.attributeNames, result, "owningAddr").sum || ""
/*
- "L*" => "* (local)"
- "M0*" => "* (direct)"
- "M1*" => "* (dequeue)"
- "MX*" => "* (phase X)"
*/
var address = undefined;
var starts = {'L': '(local)', 'M0': '(direct)', 'M1': '(dequeue)'}
for (var start in starts) {
if (owningAddr.startsWith(start)) {
var ends = owningAddr.substr(start.length)
address = ends + " " + starts[start]
break;
}
}
if (!address) {
// check for MX*
if (owningAddr.length > 3) {
if (owningAddr[0] === 'M') {
var phase = parseInt(owningAddress.substr(1))
if (phase && !isNaN(phase)) {
var phaseStr = phase + "";
var star = owningAddress.substr(2 + phaseStr.length)
address = star + " " + "(phase " + phaseStr + ")"
}
}
}
}
return address || owningAddr;
}
var adminStatus = QDRService.valFor(response.attributeNames, result, "adminStatus").sum
var operStatus = QDRService.valFor(response.attributeNames, result, "operStatus").sum
var linkName = linkName()
var linkType = QDRService.valFor(response.attributeNames, result, "linkType").sum
if ($scope.currentLinkFilter === "" || $scope.currentLinkFilter === linkType) {
linkFields.push({
link: linkName,
title: linkName,
uncounts: uncounts(),
operStatus: operStatus,
adminStatus:adminStatus,
owningAddr: fixAddress(),
deliveryCount:prettySum("deliveryCount") + " ",
rawDeliveryCount: QDRService.valFor(response.attributeNames, result, "deliveryCount").sum,
name: QDRService.valFor(response.attributeNames, result, "name").sum,
linkName: QDRService.valFor(response.attributeNames, result, "linkName").sum,
capacity: QDRService.valFor(response.attributeNames, result, "capacity").sum,
connectionId: QDRService.valFor(response.attributeNames, result, "connectionId").sum,
linkDir: QDRService.valFor(response.attributeNames, result, "linkDir").sum,
linkType: linkType,
peer: QDRService.valFor(response.attributeNames, result, "peer").sum,
type: QDRService.valFor(response.attributeNames, result, "type").sum,
undeliveredCount: QDRService.valFor(response.attributeNames, result, "undeliveredCount").sum,
unsettledCount: QDRService.valFor(response.attributeNames, result, "unsettledCount").sum,
uid: linkName,
timestamp: now,
rate: rate(response, result)
})
}
})
callbacks.forEach( function (cb) {
cb(linkFields)
})
}, nodeIds[0])
}
$scope.allConnectionFields = []
$scope.allConnectionSelections = [];
$scope.allConnectionGrid = {
saveKey: 'allConnGrid',
data: 'allConnectionFields',
columnDefs: [
{
field: 'host',
saveKey: 'allConnGrid',
displayName: 'host'
},
{
field: 'container',
displayName: 'container'
},
{
field: 'role',
displayName: 'role'
},
{
field: 'dir',
displayName: 'dir'
},
{
field: 'security',
displayName: 'security'
},
{
field: 'authentication',
displayName: 'authentication'
}
],
enableColumnResize: true,
multiSelect: false,
selectedItems: $scope.allConnectionSelections,
afterSelectionChange: function(data) {
if (data.selected) {
var selItem = $scope.allConnectionSelections[0]
var nodeId = selItem.host
// activate Routers->nodeId in the tree
$("#overtree").dynatree("getTree").activateKey(nodeId);
}
}
};
// get info for a all connections
var allConnectionInfo = function () {
var nodeIds = QDRService.nodeIdList()
updateConnectionTree(nodeIds)
$scope.allConnectionFields = [];;
var connectionNodes = $("#overtree").dynatree("getTree").getNodeByKey('Connections').getChildren()
connectionNodes.forEach( function (connection) {
$scope.allConnectionFields.push(connection.data.fields)
})
loadColState($scope.allConnectionGrid);
}
$scope.addressFields = []
$scope.addressGrid = {
saveKey: 'addGrid',
data: 'addressFields',
columnDefs: [
{
field: 'attribute',
displayName: 'Attribute',
saveKey: 'addGrid',
width: '40%'
},
{
field: 'value',
displayName: 'Value',
width: '40%'
}
],
enableColumnResize: true,
multiSelect: false
}
// get info for a single address
var addressInfo = function (address) {
if (!address)
return;
$scope.address = address
$scope.addressFields = [];
var fields = Object.keys(address.data.fields)
fields.forEach( function (field) {
if (field != "title" && field != "uid")
$scope.addressFields.push({attribute: field, value: address.data.fields[field]})
})
loadColState($scope.addressGrid);
}
$scope.singleLinkFields = []
$scope.linkGrid = {
saveKey: 'linkGrid',
data: 'singleLinkFields',
columnDefs: [
{
field: 'attribute',
displayName: 'Attribute',
width: '40%'
},
{
field: 'value',
displayName: 'Value',
width: '40%'
}
],
enableColumnResize: true,
multiSelect: false
}
// display the grid detail info for a single link
var linkInfo = function (link) {
if (!link)
return;
$scope.link = link
$scope.singleLinkFields = [];
var fields = Object.keys(link.data.fields)
var excludeFields = ["title", "uid", "uncounts", "rawDeliveryCount", "timestamp"]
fields.forEach( function (field) {
if (excludeFields.indexOf(field) == -1)
$scope.singleLinkFields.push({attribute: field, value: link.data.fields[field]})
})
loadColState($scope.linkGrid);
}
// get info for a single connection
$scope.connectionModes = [{
content: '<a><i class="icon-list"></i> Attriutes</a>',
id: 'attributes',
title: "View connection attributes",
isValid: function () { return true; }
},
{
content: '<a><i class="icon-link"></i> Links</a>',
id: 'links',
title: "Show links",
isValid: function () { return true }
}
];
$scope.currentMode = $scope.connectionModes[0];
$scope.isModeSelected = function (mode) {
return mode === $scope.currentMode;
}
$scope.connectionLinks = [];
var updateConnectionLinks = function () {
var n = $scope.connection.data.fields
var key = n.routerId
var nodeInfo = QDRService.topology.nodeInfo();
var links = nodeInfo[key]['.router.link'];
var linkTypeIndex = links.attributeNames.indexOf('linkType');
var connectionIdIndex = links.attributeNames.indexOf('connectionId');
$scope.connectionLinks = [];
links.results.forEach( function (link) {
if (link[linkTypeIndex] === 'endpoint' && link[connectionIdIndex] === n.identity) {
var l = {};
l.owningAddr = QDRService.valFor(links.attributeNames, link, 'owningAddr');
l.dir = QDRService.valFor(links.attributeNames, link, 'linkDir');
if (l.owningAddr && l.owningAddr.length > 2)
if (l.owningAddr[0] === 'M')
l.owningAddr = l.owningAddr.substr(2)
else
l.owningAddr = l.owningAddr.substr(1)
l.adminStatus = QDRService.valFor(links.attributeNames, link, 'adminStatus');
l.operStatus = QDRService.valFor(links.attributeNames, link, 'operStatus');
l.identity = QDRService.valFor(links.attributeNames, link, 'identity')
l.connectionId = QDRService.valFor(links.attributeNames, link, 'connectionId')
/*
l.deliveryCount = QDRService.pretty(QDRService.valFor(links.attributeNames, link, 'deliveryCount'));
l.undeliveredCount = QDRService.pretty(QDRService.valFor(links.attributeNames, link, 'undeliveredCount'));
l.unsettledCount = QDRService.pretty(QDRService.valFor(links.attributeNames, link, 'unsettledCount'));
*/
// ---------------------------------------------
// TODO: remove this fake quiescing/reviving logic when the routers do the work
if ($scope.quiesceState.linkStates[l.identity])
l.adminStatus = $scope.quiesceState.linkStates[l.identity];
if ($scope.quiesceState.operStates[l.identity])
l.operStatus = $scope.quiesceState.operStates[l.identity];
if ($scope.quiesceState.state == 'quiescing') {
if (l.adminStatus === 'enabled') {
var chance = Math.floor(Math.random() * 2);
if (chance == 1) {
l.adminStatus = 'disabled';
$scope.quiesceState.linkStates[l.identity] = 'disabled';
$scope.quiesceState.operStates[l.identity] = 'idle';
}
}
}
if ($scope.quiesceState.state == 'reviving') {
if (l.adminStatus === 'disabled') {
var chance = Math.floor(Math.random() * 2);
if (chance == 1) {
l.adminStatus = 'enabled';
$scope.quiesceState.linkStates[l.identity] = 'enabled';
$scope.quiesceState.operStates[l.identity] = 'up';
}
}
}
if ($scope.quiesceState.linkStates[l.identity] === 'disabled') {
l.unsettledCount = 0;
l.undeliveredCount = 0;
l.operState = 'idle'
$scope.quiesceState.operStates[l.identity] = l.operState
} else {
l.deliveryCount = QDRService.pretty(QDRService.valFor(links.attributeNames, link, 'deliveryCount'));
l.undeliveredCount = QDRService.pretty(QDRService.valFor(links.attributeNames, link, 'undeliveredCount'));
l.unsettledCount = QDRService.pretty(QDRService.valFor(links.attributeNames, link, 'unsettledCount'));
l.operState = 'up'
$scope.quiesceState.operStates[l.identity] = l.operState
}
// ---------------------------------------------
$scope.connectionLinks.push(l)
}
})
$scope.connectionLinksGrid.updateState()
}
$scope.selectMode = function (mode) {
$scope.currentMode = mode;
if (mode.id === 'links') {
QDRService.addUpdatedAction("connectionLinks", updateConnectionLinks)
updateConnectionLinks();
} else {
QDRService.delUpdatedAction("connectionLinks");
}
}
$scope.isValid = function (mode) {
return mode.isValid()
}
$scope.quiesceState = {
state: 'enabled',
buttonText: 'Quiesce',
buttonDisabled: false,
linkStates: {},
operStates: {}
}
$scope.quiesceAllClicked = function () {
var state = $scope.quiesceState.state;
if (state === 'enabled') {
// start quiescing all links
$scope.quiesceState.state = 'quiescing';
} else if (state === 'quiesced') {
// start reviving all links
$scope.quiesceState.state = 'reviving';
}
$scope.connectionLinksGrid.updateState();
}
$scope.quiesceClass = function (row) {
var stateClassMap = {
enabled: 'btn-primary',
quiescing: 'btn-warning',
reviving: 'btn-warning',
quiesced: 'btn-danger'
}
return stateClassMap[$scope.quiesceState.state];
}
$scope.quiesceLinkClass = function (row) {
var stateClassMap = {
enabled: 'btn-primary',
disabled: 'btn-danger'
}
return stateClassMap[row.entity.adminStatus]
}
$scope.quiesceLink = function (row) {
var state = row.entity.adminStatus === 'enabled' ? 'disabled' : 'enabled';
var operState = state === 'enabled' ? 'up' : 'idle';
$scope.quiesceState.linkStates[row.entity.identity] = state;
$scope.quiesceState.operStates[row.entity.identity] = operState;
}
$scope.quiesceLinkDisabled = function (row) {
return false;
}
$scope.quiesceLinkText = function (row) {
return row.entity.adminStatus === 'disabled' ? "Revive" : "Quiesce";
}
$scope.quiesceHide = function () {
return $scope.connectionLinks.length == 0;
}
$scope.connectionLinksGrid = {
saveKey: 'connLinksGrid',
data: 'connectionLinks',
updateState: function () {
var state = $scope.quiesceState.state;
// count enabled and disabled links for this connection
var enabled = 0, disabled = 0;
$scope.connectionLinks.forEach ( function (link) {
if (link.adminStatus === 'enabled')
++enabled;
if (link.adminStatus === 'disabled')
++disabled;
})
var linkCount = $scope.connectionLinks.length;
if (linkCount == 0) {
$scope.quiesceState.buttonText = 'Quiesce';
$scope.quiesceState.buttonDisabled = false;
$scope.quiesceState.state = 'enabled'
return;
}
// if state is quiescing and any links are enabled, button should say 'Quiescing' and be disabled
if (state === 'quiescing' && (enabled > 0)) {
$scope.quiesceState.buttonText = 'Quiescing';
$scope.quiesceState.buttonDisabled = true;
} else
// if state is enabled and all links are disabled, button should say Revive and be enabled. set state to quisced
// if state is quiescing and all links are disabled, button should say 'Revive' and be enabled. set state to quiesced
if ((state === 'quiescing' || state === 'enabled') && (disabled === linkCount)) {
$scope.quiesceState.buttonText = 'Revive';
$scope.quiesceState.buttonDisabled = false;
$scope.quiesceState.state = 'quiesced'
} else
// if state is reviving and any links are disabled, button should say 'Reviving' and be disabled
if (state === 'reviving' && (disabled > 0)) {
$scope.quiesceState.buttonText = 'Reviving';
$scope.quiesceState.buttonDisabled = true;
} else
// if state is reviving or quiesced and all links are enabled, button should say 'Quiesce' and be enabled. set state to enabled
if ((state === 'reviving' || state === 'quiesced') && (enabled === linkCount)) {
$scope.quiesceState.buttonText = 'Quiesce';
$scope.quiesceState.buttonDisabled = false;
$scope.quiesceState.state = 'enabled'
}
if ($scope.quiesceState.state === 'quiesced') {
d3.selectAll('.external.connection.dynatree-active')
.classed('quiesced', true)
} else {
d3.selectAll('.external.connection.dynatree-active.quiesced')
.classed('quiesced', false)
}
},
columnDefs: [
{
field: 'adminStatus',
cellTemplate: "titleCellTemplate.html",
headerCellTemplate: 'titleHeaderCellTemplate.html',
saveKey: 'connLinksGrid',
displayName: 'Admin state'
},
{
field: 'operStatus',
cellTemplate: "titleCellTemplate.html",
headerCellTemplate: 'titleHeaderCellTemplate.html',
displayName: 'Oper state'
},
{
field: 'dir',
cellTemplate: "titleCellTemplate.html",
headerCellTemplate: 'titleHeaderCellTemplate.html',
displayName: 'dir'
},
{
field: 'owningAddr',
cellTemplate: "titleCellTemplate.html",
headerCellTemplate: 'titleHeaderCellTemplate.html',
displayName: 'Address'
},
{
field: 'deliveryCount',
displayName: 'Delivered',
headerCellTemplate: 'titleHeaderCellTemplate.html',
cellClass: 'grid-values'
},
{
field: 'undeliveredCount',
displayName: 'Undelivered',
headerCellTemplate: 'titleHeaderCellTemplate.html',
cellClass: 'grid-values'
},
{
field: 'unsettledCount',
displayName: 'Unsettled',
headerCellTemplate: 'titleHeaderCellTemplate.html',
cellClass: 'grid-values'
}/*,
{
cellClass: 'gridCellButton',
cellTemplate: '<button title="{{quiesceLinkText(row)}} this link" type="button" ng-class="quiesceLinkClass(row)" class="btn" ng-click="quiesceLink(row)" ng-disabled="quiesceLinkDisabled(row)">{{quiesceLinkText(row)}}</button>'
}*/
]
}
$scope.connectionFields = []
$scope.connectionGrid = {
saveKey: 'connGrid',
data: 'connectionFields',
columnDefs: [
{
field: 'attribute',
displayName: 'Attribute',
saveKey: 'connGrid',
width: '40%'
},
{
field: 'value',
displayName: 'Value',
width: '40%'
}
],
enableColumnResize: true,
multiSelect: false
}
var connectionInfo = function (connection) {
$scope.connection = connection
$scope.connectionFields = [];
var fields = Object.keys(connection.data.fields)
fields.forEach( function (field) {
$scope.connectionFields.push({attribute: field, value: connection.data.fields[field]})
})
$scope.selectMode($scope.currentMode)
loadColState($scope.connectionGrid);
}
// get info for a all logs
var allLogInfo = function () {
}
// get info for a single log
var logInfo = function (node) {
$scope.log = node
}
var getExpandedList = function () {
var list = [];
var tree = $("#overtree").dynatree("getRoot");
if (tree.length !== 0) {
tree.visit(function(node){
if (node.isExpanded()) {
list.push(node.data.parent)
}
});
}
return list;
}
var updateExpanded = function () {
var tree = $("#overtree").dynatree("getRoot");
if (tree.length !== 0) {
tree.visit(function(node){
if (node.isExpanded() || node.isActive()) {
node.data.info(node)
}
});
}
}
// loads the tree node name that was last selected
var loadActivatedNode = function () {
return localStorage[OverviewActivatedKey] || 'Routers'
}
// saved the tree node name that is currently selected
var saveActivated = function (key) {
localStorage[OverviewActivatedKey] = key;
lastKey = key;
}
// loads list that was saved
var loadExpandedNodeList = function () {
return angular.fromJson(localStorage[OverviewExpandedKey]) || [];
}
// called when a node is expanded
// here we save the expanded node so it can be restored when the page reloads
var saveExpanded = function () {
var list = getExpandedList();
localStorage[OverviewExpandedKey] = JSON.stringify(list)
}
// activated is called each time a tree node is clicked
// based on which node is clicked, load the correct data grid template and start getting the data
var activated = function (node) {
//QDR.log.debug("node activated: " + node.data.title)
var type = node.data.type;
saveExpanded()
saveActivated(node.data.key)
var template = $scope.templates.filter( function (tpl) {
return tpl.name == type;
})
$scope.template = template[0];
// the nodes info function will fetch the grids data
if (node.data.info) {
$timeout(function () {node.data.info(node)})
}
}
$scope.template = {url: ''};
if (!QDRService.connected) {
QDRService.redirectWhenConnected("overview")
return;
}
// we are currently connected. setup a handler to get notified if we are ever disconnected
QDRService.addDisconnectAction( function () {
QDRService.redirectWhenConnected("overview")
$scope.$apply();
})
/* --------------------------------------------------
*
* setup the tree on the left
*
* -------------------------------------------------
*/
// utility function called by each top level tree node when it needs to populate its child nodes
var updateLeaves = function (leaves, parentKey, parentFolder, worker) {
var scrollTree = $('.qdr-overview.pane.left .pane-viewport')
var scrollTop = scrollTree.scrollTop();
var tree = $("#overtree").dynatree("getTree")
var parentNode = tree.count ? tree.getNodeByKey(parentKey) : null;
// if we were called after the tree is created, replace the existing nodes
var activeNode;
if (parentNode) {
activeNode = tree.getActiveNode();
parentNode.removeChildren();
}
leaves.forEach( function (leaf) {
var childFolder = worker(leaf)
if (parentNode)
parentNode.addChild(childFolder)
else
parentFolder.children.push(childFolder)
})
scrollTree.scrollTop(scrollTop)
if (activeNode) {
var newNode = tree.getNodeByKey(activeNode.data.key)
newNode.activateSilently()
}
}
// get saved tree state
var lastKey = loadActivatedNode();
var expandedNodeList = loadExpandedNodeList();
// create a routers tree branch
var routers = new Folder("Routers")
routers.type = "Routers"
routers.info = allRouterInfo
routers.activate = lastKey === 'Routers'
routers.expand = (expandedNodeList.indexOf("Routers") > -1)
routers.clickFolderMode = 1
routers.key = "Routers"
routers.parent = "Routers"
routers.addClass = "routers"
topLevelChildren.push(routers)
// called when the list of routers changes
var updateRouterTree = function (nodes) {
var worker = function (node) {
var name = QDRService.nameFromId(node)
var router = new Folder(name)
router.type = "Router"
router.info = routerInfo
router.nodeId = node
router.key = node
router.addClass = "router"
router.parent = "Routers"
router.activate = lastKey === node
return router;
}
updateLeaves(nodes, "Routers", routers, worker)
}
updateRouterTree(QDRService.nodeIdList());
// create an addresses tree branch
var addresses = new Folder("Addresses")
addresses.type = "Addresses"
addresses.info = allAddressInfo
addresses.activate = lastKey === 'Addresses'
addresses.expand = (expandedNodeList.indexOf("Addresses") > -1)
addresses.clickFolderMode = 1
addresses.key = "Addresses"
addresses.parent = "Addresses"
addresses.addClass = "addresses"
topLevelChildren.push(addresses)
var updateAddressTree = function (addressFields) {
var worker = function (address) {
var a = new Folder(address.title)
a.info = addressInfo
a.key = address.uid
a.fields = address
a.type = "Address"
a.addClass = "address"
a.activate = lastKey === address.uid
a.parent = "Addresses"
return a;
}
updateLeaves(addressFields, "Addresses", addresses, worker)
}
allAddressInfo();
$scope.setLinkFilter = function (cur) {
// filter out non-matching links from the tree and the grid
getAllLinkFields([updateLinkGrid, updateLinkTree])
}
$scope.filterClose = function () {
var filter = $('#linkFilter')
filter.hide();
}
$scope.currentLinkFilter = "endpoint"
var filterHtml = "<button type='button' class='btn btn-secondary btn-filter'><span class='filter-icon'><i class='icon-filter'> Filter</span></button>";
var links = new Folder("Links " + filterHtml)
links.type = "Links"
links.info = allLinkInfo
links.activate = lastKey === 'Links'
links.expand = (expandedNodeList.indexOf("Links") > -1)
links.clickFolderMode = 1
links.key = "Links"
links.parent = "Links"
links.addClass = "links"
topLevelChildren.push(links)
// called both before the tree is created and whenever a background update is done
var updateLinkTree = function (linkFields) {
var worker = function (link) {
var l = new Folder(link.title)
l.info = linkInfo
l.key = link.uid
l.fields = link
l.type = "Link"
l.parent = "Links"
l.activate = lastKey === link.uid
l.addClass = "link"
return l;
}
linkFields.sort ( function (a,b) { return a.link < b.link ? -1 : a.link > b.link ? 1 : 0})
updateLeaves(linkFields, "Links", links, worker)
}
allLinkInfo();
var connections = new Folder("Connections")
connections.type = "Connections"
connections.info = allConnectionInfo
connections.activate = lastKey === 'Connections'
connections.expand = (expandedNodeList.indexOf("Connections") > -1)
connections.clickFolderMode = 1
connections.key = "Connections"
connections.parent = "Connections"
connections.addClass = "connections"
topLevelChildren.push(connections)
updateConnectionTree = function (nodes) {
var connectionsObj = {}
var expected = nodes.length;
var connreceived = 0;
nodes.forEach( function (nodeId) {
QDRService.getNodeInfo(nodeId, ".connection", [], function (nodeName, entity, response) {
response.results.forEach( function (result) {
var auth = "no_auth"
var sasl = QDRService.valFor(response.attributeNames, result, "sasl")
if (QDRService.valFor(response.attributeNames, result, "isAuthenticated")) {
auth = sasl
if (sasl === "ANONYMOUS")
auth = "anonymous-user"
else {
if (sasl === "GSSAPI")
sasl = "Kerberos"
if (sasl === "EXTERNAL")
sasl = "x.509"
auth = QDRService.valFor(response.attributeNames, result, "user") + "(" +
QDRService.valFor(response.attributeNames, result, "sslCipher") + ")"
}
}
var sec = "no-security"
if (QDRService.valFor(response.attributeNames, result, "isEncrypted")) {
if (sasl === "GSSAPI")
sec = "Kerberos"
else
sec = QDRService.valFor(response.attributeNames, result, "sslProto") + "(" +
QDRService.valFor(response.attributeNames, result, "sslCipher") + ")"
}
var host = QDRService.valFor(response.attributeNames, result, "host")
connectionsObj[host] = {}
response.attributeNames.forEach( function (attribute, i) {
connectionsObj[host][attribute] = result[i]
})
connectionsObj[host].security = sec
connectionsObj[host].authentication = auth
connectionsObj[host].routerId = nodeName
})
++connreceived;
if (connreceived == expected) {
var worker = function (connection) {
var c = new Folder(connection)
c.type = "Connection"
c.info = connectionInfo
c.key = connection
c.fields = connectionsObj[connection]
c.tooltip = connectionsObj[connection].role === "inter-router" ? "inter-router connection" : "external connection"
c.addClass = c.tooltip
c.parent = "Connections"
c.activate = lastKey === connection
return c
}
var allConnections = Object.keys(connectionsObj).sort()
updateLeaves(allConnections, "Connections", connections, worker)
}
})
})
}
updateConnectionTree(QDRService.nodeIdList())
var logsreceived = 0;
var logObj = {}
var logs = new Folder("Logs")
logs.type = "Logs"
logs.info = allLogInfo
logs.activate = lastKey === 'Logs'
logs.expand = (expandedNodeList.indexOf("Logs") > -1)
logs.clickFolderMode = 1
logs.key = "Logs"
logs.parent = "Logs"
//topLevelChildren.push(logs)
var nodeIds = QDRService.nodeIdList()
var expected = nodeIds.length;
nodeIds.forEach( function (nodeId) {
QDRService.getNodeInfo(nodeId, ".log", ["name"], function (nodeName, entity, response) {
response.results.forEach( function (result) {
logObj[result[0]] = 1 // use object to collapse duplicates
})
++logsreceived;
if (logsreceived == expected) {
var allLogs = Object.keys(logObj).sort()
allLogs.forEach(function (log) {
var l = new Folder(log)
l.type = "Log"
l.info = logInfo
l.key = log
l.parent = "Logs"
l.activate = lastKey === log
logs.children.push(l)
})
$('#overtree').dynatree({
onActivate: activated,
onExpand: saveExpanded,
onClick: function (n, e) {
if (e.target.className.indexOf('-filter') > -1) {
//QDR.log.debug("overtree on click called")
e.preventDefault();
e.stopPropagation()
var filter = $('#linkFilter')
var treeLink = $('span.links')
filter.css({
top: treeLink.offset().top + treeLink.height(),
left: treeLink.offset().left,
zIndex:5000
});
filter.toggle()
$("#overtree").dynatree("getTree").getNodeByKey('Links').activate()
return false;
}
},
selectMode: 1,
activeVisible: false,
children: topLevelChildren
})
// simulate a click on the previous active node
var active = $("#overtree").dynatree("getActiveNode");
if (!active) {
active = $("#overtree").dynatree("getTree").getNodeByKey("Routers")
}
activated(active);
// populate the data for each expanded node
updateExpanded();
QDRService.addUpdatedAction( "overview", function () {
$timeout(updateExpanded);
})
// update the node list
QDRService.startUpdating()
loadColState($scope.allRouters);
loadColState($scope.routerGrid);
loadColState($scope.addressesGrid);
loadColState($scope.addressGrid);
loadColState($scope.linksGrid);
loadColState($scope.linkGrid);
loadColState($scope.allConnectionGrid);
loadColState($scope.connectionGrid);
}
})
})
$scope.$on("$destroy", function( event ) {
QDRService.stopUpdating()
QDRService.delUpdatedAction("overview")
if (currentTimer) {
clearTimeout(currentTimer)
currentTimer = null;
}
});
}]);
return QDR;
}(QDR || {}));