| /* |
| 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', '$timeout', '$uibModal', function($scope, QDRService, $location, $timeout, $uibModal) { |
| |
| console.log("QDR.OverviewControll started with location of " + $location.path() + " and connection of " + QDRService.connected); |
| var COLUMNSTATEKEY = 'QDRColumnKey.'; |
| var OVERVIEWEXPANDEDKEY = "QDROverviewExpanded" |
| var OVERVIEWACTIVATEDKEY = "QDROverviewActivated" |
| var FILTERKEY = "QDROverviewFilters" |
| var OVERVIEWMODEIDS = "QDROverviewModeIds" |
| var treeRoot; // the dynatree root node. initialized once log data is received |
| |
| // 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 refreshInterval = 5000 |
| $scope.modes = [ |
| {title: 'Overview', name: 'Overview', right: false} |
| ]; |
| |
| $scope.tmplOverviewTree = QDR.templatePath + 'tmplOverviewTree.html'; |
| $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: 'logModule.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.routerPagingOptions = { |
| pageSizes: [50, 100, 500], |
| pageSize: 50, |
| currentPage: 1 |
| }; |
| var getPagedData = function (pageSize, page) { |
| $scope.totalRouters = $scope.allRouterFields.length |
| $scope.allRouters.showFooter = $scope.totalRouters > 50 |
| $scope.pagedRouterFields = $scope.allRouterFields.slice((page - 1) * pageSize, page * pageSize); |
| } |
| $scope.$watch('pagingOptions', function (newVal, oldVal) { |
| if (newVal !== oldVal && newVal.currentPage !== oldVal.currentPage) { |
| getPagedData($scope.routerPagingOptions.pageSize, $scope.routerPagingOptions.currentPage); |
| } |
| }, true); |
| |
| $scope.totalRouters = 0; |
| $scope.allRouterFields = []; |
| $scope.pagedRouterFields = []; |
| $scope.allRouterSelections = []; |
| $scope.allRouters = { |
| saveKey: 'allRouters', |
| data: 'pagedRouterFields', |
| columnDefs: [ |
| { |
| field: 'id', |
| 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, |
| enablePaging: true, |
| showFooter: $scope.totalRouters > 50, |
| totalServerItems: 'totalRouters', |
| pagingOptions: $scope.routerPagingOptions, |
| multiSelect: false, |
| selectedItems: $scope.allRouterSelections, |
| plugins: [new ngGridFlexibleHeightPlugin()], |
| 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 nodes = {} |
| // gets called each node/entity response |
| var gotNode = function (nodeName, entity, response) { |
| if (!nodes[nodeName]) |
| nodes[angular.copy(nodeName)] = {} |
| nodes[nodeName][entity] = angular.copy(response); |
| } |
| // send the requests for all connection and router info for all routers |
| QDRService.fetchAllEntities([{entity: ".connection", attrs: ["role"]}], function () { |
| QDRService.fetchAllEntities([{entity: ".router"}], function () { |
| // we have all the data now in the nodes object |
| var allRouterFields = [] |
| for (var node in nodes) { |
| var connections = 0 |
| for (var i=0; i<nodes[node][".connection"].results.length; ++i) { |
| // we only requested "role" so it will be at [0] |
| if (nodes[node][".connection"].results[i][0] === 'inter-router') |
| ++connections |
| } |
| var routerRow = {connections: connections, nodeId: node, id: QDRService.nameFromId(node)} |
| nodes[node][".router"].attributeNames.forEach( function (routerAttr, i) { |
| if (routerAttr !== "routerId" && routerAttr !== "id") |
| routerRow[routerAttr] = nodes[node][".router"].results[0][i] |
| }) |
| allRouterFields.push(routerRow) |
| } |
| $timeout(function () { |
| $scope.allRouterFields = allRouterFields |
| getPagedData($scope.routerPagingOptions.pageSize, $scope.routerPagingOptions.currentPage); |
| updateRouterTree(nodeIds) |
| scheduleNextUpdate() |
| //if ($scope.router) |
| // routerInfo($scope.router) |
| }) |
| }, gotNode) |
| }, gotNode) |
| loadColState($scope.allRouters) |
| } |
| |
| $scope.routerFields = [] |
| $scope.routerGrid = { |
| saveKey: 'routerGrid', |
| data: 'routerFields', |
| columnDefs: [ |
| { |
| field: 'attribute', |
| displayName: 'Attribute', |
| saveKey: 'routerGrid', |
| }, |
| { |
| field: 'value', |
| displayName: 'Value', |
| } |
| ], |
| enableColumnResize: true, |
| multiSelect: false |
| } |
| |
| $scope.router = null; |
| // get info for a single router |
| var routerInfo = function (node) { |
| $scope.router = node |
| |
| var routerFields = []; |
| $scope.allRouterFields.some( function (field) { |
| if (field.id === node.data.title) { |
| Object.keys(field).forEach ( function (key) { |
| if (key !== '$$hashKey') { |
| var attr = (key === 'connections') ? 'External connections' : key |
| routerFields.push({attribute: attr, value: field[key]}) |
| } |
| }) |
| return true |
| } |
| }) |
| $timeout(function () {$scope.routerFields = routerFields}) |
| scheduleNextUpdate() |
| loadColState($scope.routerGrid); |
| } |
| |
| $scope.addressPagingOptions = { |
| pageSizes: [50, 100, 500], |
| pageSize: 50, |
| currentPage: 1 |
| }; |
| var getAddressPagedData = function (pageSize, page) { |
| $scope.totalAddresses = $scope.addressesData.length |
| $scope.addressesGrid.showFooter = $scope.totalAddresses > 50 |
| $scope.pagedAddressesData = $scope.addressesData.slice((page - 1) * pageSize, page * pageSize); |
| } |
| $scope.$watch('addressPagingOptions', function (newVal, oldVal) { |
| if (newVal !== oldVal && newVal.currentPage !== oldVal.currentPage) { |
| getAddressPagedData($scope.addressPagingOptions.pageSize, $scope.addressPagingOptions.currentPage); |
| } |
| }, true); |
| |
| $scope.totalAddresses = 0; |
| $scope.pagedAddressesData = [] |
| $scope.addressesData = [] |
| $scope.selectedAddresses = [] |
| $scope.addressesGrid = { |
| saveKey: 'addressesGrid', |
| data: 'pagedAddressesData', |
| 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' |
| } |
| ], |
| enablePaging: true, |
| showFooter: $scope.totalAddresses > 50, |
| totalServerItems: 'totalAddresses', |
| pagingOptions: $scope.addressPagingOptions, |
| enableColumnResize: true, |
| multiSelect: false, |
| selectedItems: $scope.selectedAddresses, |
| plugins: [new ngGridFlexibleHeightPlugin()], |
| 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 nodes = {} |
| // gets called each node/entity response |
| var gotNode = function (nodeName, entity, response) { |
| if (!nodes[nodeName]) |
| nodes[nodeName] = {} |
| nodes[nodeName][entity] = angular.copy(response); |
| } |
| 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" |
| if (addr[0] == 'T') return "topo" |
| return "unknown: " + addr[0] |
| } |
| var addr_phase = function (addr) { |
| if (!addr) |
| return "-" |
| if (addr[0] == 'M') |
| return addr[1] |
| return '' |
| } |
| var prettyVal = function (val) { |
| return QDRService.pretty(val || "-") |
| } |
| var addressFields = [] |
| var addressObjs = {} |
| // send the requests for all connection and router info for all routers |
| QDRService.fetchAllEntities({entity: ".router.address"}, function () { |
| for (var node in nodes) { |
| var response = nodes[node][".router.address"] |
| response.results.forEach( function (result) { |
| var address = QDRService.flatten(response.attributeNames, result) |
| |
| var addNull = function (oldVal, newVal) { |
| if (oldVal != null && newVal != null) |
| return oldVal + newVal |
| if (oldVal != null) |
| return oldVal |
| return newVal |
| } |
| |
| var uid = address.identity |
| var identity = QDRService.identity_clean(uid) |
| |
| if (!addressObjs[QDRService.addr_text(identity)+QDRService.addr_class(identity)]) |
| addressObjs[QDRService.addr_text(identity)+QDRService.addr_class(identity)] = { |
| address: QDRService.addr_text(identity), |
| 'class': QDRService.addr_class(identity), |
| phase: addr_phase(identity), |
| inproc: address.inProcess, |
| local: address.subscriberCount, |
| remote: address.remoteCount, |
| 'in': address.deliveriesIngress, |
| out: address.deliveriesEgress, |
| thru: address.deliveriesTransit, |
| toproc: address.deliveriesToContainer, |
| fromproc:address.deliveriesFromContainer, |
| uid: uid |
| } |
| else { |
| var sumObj = addressObjs[QDRService.addr_text(identity)+QDRService.addr_class(identity)] |
| sumObj.inproc = addNull(sumObj.inproc, address.inproc) |
| sumObj.local = addNull(sumObj.local, address.local) |
| sumObj.remote = addNull(sumObj.remote, address.remote) |
| sumObj['in'] = addNull(sumObj['in'], address['in']) |
| sumObj.out = addNull(sumObj.out, address.out) |
| sumObj.thru = addNull(sumObj.thru, address.thru) |
| sumObj.toproc = addNull(sumObj.toproc, address.toproc) |
| sumObj.fromproc = addNull(sumObj.fromproc, address.fromproc) |
| } |
| /* |
| addressFields.push({ |
| address: QDRService.addr_text(identity), |
| 'class': QDRService.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 |
| }) |
| */ |
| }) |
| } |
| for (var obj in addressObjs) { |
| addressObjs[obj].inproc = prettyVal(addressObjs[obj].inproc) |
| addressObjs[obj].local = prettyVal(addressObjs[obj].local) |
| addressObjs[obj].remote = prettyVal(addressObjs[obj].remote) |
| addressObjs[obj]['in'] = prettyVal(addressObjs[obj]['in']) |
| addressObjs[obj].out = prettyVal(addressObjs[obj].out) |
| addressObjs[obj].thru = prettyVal(addressObjs[obj].thru) |
| addressObjs[obj].toproc = prettyVal(addressObjs[obj].toproc) |
| addressObjs[obj].fromproc = prettyVal(addressObjs[obj].fromproc) |
| addressFields.push(addressObjs[obj]) |
| } |
| if (addressFields.length === 0) |
| return; |
| // update the grid's data |
| addressFields.sort ( function (a,b) { |
| return a.address + a['class'] < b.address + b['class'] ? -1 : a.address + a['class'] > b.address + b['class'] ? 1 : 0} |
| ) |
| // callapse all records with same addres+class |
| for (var i=1; i<addressFields.length; ++i) { |
| |
| } |
| addressFields[0].title = addressFields[0].address |
| for (var i=1; i<addressFields.length; ++i) { |
| // if this address is the same as the previous address, add a class to the display titles |
| 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 |
| } |
| $timeout(function () { |
| $scope.addressesData = addressFields |
| getAddressPagedData($scope.addressPagingOptions.pageSize, $scope.addressPagingOptions.currentPage); |
| // repopulate the tree's child nodes |
| updateAddressTree(addressFields) |
| scheduleNextUpdate() |
| }) |
| }, gotNode) |
| loadColState($scope.addressesGrid); |
| } |
| |
| var updateLinkGrid = function ( linkFields ) { |
| // apply the filter |
| var filteredLinks = linkFields.filter( function (link) { |
| var include = true; |
| if ($scope.filter.endpointsOnly === "true") { |
| if (link.linkType !== 'endpoint') |
| include = false; |
| } |
| if ($scope.filter.hideConsoles) { |
| if (QDRService.isConsoleLink(link)) |
| include = false; |
| } |
| return include; |
| }) |
| QDR.log.debug("setting linkFields in updateLinkGrid") |
| $scope.linkFields = filteredLinks; |
| getLinkPagedData($scope.linkPagingOptions.pageSize, $scope.linkPagingOptions.currentPage); |
| // 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.linkPagingOptions = { |
| pageSizes: [50, 100, 500], |
| pageSize: 50, |
| currentPage: 1 |
| }; |
| var getLinkPagedData = function (pageSize, page) { |
| $scope.totalLinks = $scope.linkFields.length |
| $scope.linksGrid.showFooter = $scope.totalLinks > 50 |
| $scope.pagedLinkData = $scope.linkFields.slice((page - 1) * pageSize, page * pageSize); |
| } |
| $scope.$watch('linkPagingOptions', function (newVal, oldVal) { |
| if (newVal !== oldVal && newVal.currentPage !== oldVal.currentPage) { |
| getLinkPagedData($scope.linkPagingOptions.pageSize, $scope.linkPagingOptions.currentPage); |
| } |
| }, true); |
| |
| $scope.totalLinks = 0; |
| $scope.pagedLinkData = [] |
| $scope.selectedLinks = [] |
| |
| var linkRowTmpl = "<div ng-class=\"{linkDirIn: row.getProperty('linkDir') == 'in', linkDirOut: row.getProperty('linkDir') == 'out'}\">" + |
| "<div ng-style=\"{ 'cursor': row.cursor }\" ng-repeat=\"col in renderedColumns\" ng-class=\"col.colIndex()\" class=\"ngCell {{col.cellClass}}\">" + |
| "<div class=\"ngVerticalBar\" ng-style=\"{height: rowHeight}\" ng-class=\"{ ngVerticalBarVisible: !$last }\"> </div>" + |
| "<div ng-cell></div>" + |
| "</div>" + |
| "</div>"; |
| |
| $scope.linksGrid = { |
| saveKey: 'linksGrid', |
| data: 'pagedLinkData', |
| columnDefs: [ |
| { |
| field: 'link', |
| displayName: 'Link', |
| groupable: false, |
| saveKey: 'linksGrid', |
| width: '11%' |
| }, |
| { |
| field: 'linkType', |
| displayName: 'Link type', |
| groupable: false, |
| width: '9%' |
| }, |
| { |
| field: 'linkDir', |
| displayName: 'Link dir', |
| groupable: false, |
| width: '8%' |
| }, |
| { |
| field: 'adminStatus', |
| displayName: 'Admin status', |
| groupable: false, |
| width: '9%' |
| }, |
| { |
| field: 'operStatus', |
| displayName: 'Oper status', |
| groupable: false, |
| width: '9%' |
| }, |
| { |
| field: 'deliveryCount', |
| displayName: 'Delivery Count', |
| groupable: false, |
| cellClass: 'grid-align-value', |
| width: '11%' |
| }, |
| { |
| field: 'rate', |
| displayName: 'Rate', |
| groupable: false, |
| cellClass: 'grid-align-value', |
| width: '8%' |
| }, |
| { |
| field: 'uncounts', |
| displayName: 'Outstanding', |
| groupable: false, |
| cellClass: 'grid-align-value', |
| width: '9%' |
| }, |
| { |
| field: 'owningAddr', |
| displayName: 'Address', |
| groupable: false, |
| width: '15%' |
| }/*, |
| { |
| displayName: 'Quiesce', |
| cellClass: 'gridCellButton', |
| cellTemplate: '<button title="{{quiesceLinkText(row)}} this link" type="button" ng-class="quiesceLinkClass(row)" class="btn" ng-click="quiesceLink(row, $event)" ng-disabled="quiesceLinkDisabled(row)">{{quiesceLinkText(row)}}</button>', |
| width: '10%' |
| }*/ |
| ], |
| enablePaging: true, |
| showFooter: $scope.totalLinks > 50, |
| totalServerItems: 'totalLinks', |
| pagingOptions: $scope.linkPagingOptions, |
| enableColumnResize: true, |
| enableColumnReordering: true, |
| showColumnMenu: true, |
| rowTemplate: linkRowTmpl, |
| multiSelect: false, |
| selectedItems: $scope.selectedLinks, |
| plugins: [new ngGridFlexibleHeightPlugin()], |
| 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) { |
| return; |
| if (!grid) |
| return; |
| var columns = localStorage.getItem(COLUMNSTATEKEY+grid.saveKey); |
| if (columns) { |
| var cols = JSON.parse(columns); |
| cols.forEach( function (col, index) { |
| if (grid.columnDefs[index]) { |
| grid.columnDefs[index].width = col[0]; |
| grid.columnDefs[index].visible = col[1] |
| } |
| }) |
| } |
| } |
| var allLinkInfo = function () { |
| var gridCallback = function (linkFields) { |
| QDRService.ensureAllEntities({entity: ".connection", force: true}, function () { |
| // only update the grid with these fields if the List tree node is selected |
| // this is becuase we are using the link grid in other places and we don't want to overwrite it |
| if ($scope.template.name === "Links") |
| updateLinkGrid(linkFields) |
| updateLinkTree(linkFields) |
| }) |
| } |
| getAllLinkFields([gridCallback, scheduleNextUpdate]) |
| loadColState($scope.linksGrid); |
| } |
| |
| var getAllLinkFields = function (completionCallbacks, selectionCallback) { |
| if (!$scope.linkFields) { |
| QDR.log.info("$scope.linkFields was not defined") |
| return; |
| } |
| var nodeIds = QDRService.nodeIdList() |
| var linkFields = [] |
| var now = Date.now() |
| var rate = function (linkName, response, result) { |
| if (!$scope.linkFields) |
| return 0; |
| var oldname = $scope.linkFields.filter(function (link) { |
| return link.link === linkName |
| }) |
| if (oldname.length === 1) { |
| var elapsed = (now - oldname[0].timestamp) / 1000; |
| if (elapsed < 0) |
| return 0 |
| var delivered = QDRService.valFor(response.attributeNames, result, "deliveryCount") - 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 |
| } |
| } |
| var expected = nodeIds.length; |
| var received = 0; |
| var gotLinkInfo = function (nodeName, entity, response) { |
| response.results.forEach( function (result) { |
| var nameIndex = response.attributeNames.indexOf('name') |
| var prettyVal = function (field) { |
| var fieldIndex = response.attributeNames.indexOf(field) |
| if (fieldIndex < 0) { |
| return "-" |
| } |
| var val = result[fieldIndex] |
| return QDRService.pretty(val) |
| } |
| var uncounts = function () { |
| var und = QDRService.valFor(response.attributeNames, result, "undeliveredCount") |
| var uns = QDRService.valFor(response.attributeNames, result, "unsettledCount") |
| return QDRService.pretty(und + uns) |
| } |
| var linkName = function () { |
| var namestr = QDRService.nameFromId(nodeName) |
| return namestr + ':' + QDRService.valFor(response.attributeNames, result, "identity") |
| } |
| var fixAddress = function () { |
| var addresses = [] |
| var owningAddr = QDRService.valFor(response.attributeNames, result, "owningAddr") || "" |
| var rawAddress = owningAddr |
| /* |
| - "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] |
| rawAddress = ends |
| 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 + ")" |
| } |
| } |
| } |
| } |
| addresses[0] = address || owningAddr |
| addresses[1] = rawAddress |
| return addresses |
| } |
| if (!selectionCallback || selectionCallback(response, result)) { |
| var adminStatus = QDRService.valFor(response.attributeNames, result, "adminStatus") |
| var operStatus = QDRService.valFor(response.attributeNames, result, "operStatus") |
| var linkName = linkName() |
| var linkType = QDRService.valFor(response.attributeNames, result, "linkType") |
| var addresses = fixAddress(); |
| var link = QDRService.flatten(response.attributeNames, result) |
| linkFields.push({ |
| link: linkName, |
| title: linkName, |
| uncounts: uncounts(), |
| operStatus: operStatus, |
| adminStatus:adminStatus, |
| owningAddr: addresses[0], |
| |
| acceptedCount: prettyVal("acceptedCount"), |
| modifiedCount: prettyVal("modifiedCount"), |
| presettledCount: prettyVal("presettledCount"), |
| rejectedCount: prettyVal("rejectedCount"), |
| releasedCount: prettyVal("releasedCount"), |
| deliveryCount:prettyVal("deliveryCount") + " ", |
| |
| rate: QDRService.pretty(rate(linkName, response, result)), |
| capacity: link.capacity, |
| undeliveredCount: link.undeliveredCount, |
| unsettledCount: link.unsettledCount, |
| |
| rawAddress: addresses[1], |
| rawDeliveryCount: link.deliveryCount, |
| name: link.name, |
| linkName: link.linkName, |
| connectionId: link.connectionId, |
| linkDir: link.linkDir, |
| linkType: linkType, |
| peer: link.peer, |
| type: link.type, |
| |
| uid: linkName, |
| timestamp: now, |
| nodeId: nodeName, |
| identity: link.identity, |
| }) |
| } |
| }) |
| if (expected === ++received) { |
| linkFields.sort ( function (a,b) { return a.link < b.link ? -1 : a.link > b.link ? 1 : 0}) |
| completionCallbacks.forEach( function (cb) { |
| cb(linkFields) |
| }) |
| } |
| } |
| nodeIds.forEach( function (nodeId) { |
| QDRService.fetchEntity(nodeId, "router.link", [], gotLinkInfo); |
| }) |
| } |
| |
| $scope.connectionPagingOptions = { |
| pageSizes: [50, 100, 500], |
| pageSize: 50, |
| currentPage: 1 |
| }; |
| var getConnectionPagedData = function (pageSize, page) { |
| $scope.totalConnections = $scope.allConnectionFields.length |
| $scope.allConnectionGrid.showFooter = $scope.totalConnections > 50 |
| $scope.pagedConnectionsData = $scope.allConnectionFields.slice((page - 1) * pageSize, page * pageSize); |
| } |
| $scope.$watch('connectionPagingOptions', function (newVal, oldVal) { |
| if (newVal !== oldVal && newVal.currentPage !== oldVal.currentPage) { |
| getConnectionPagedData($scope.connectionPagingOptions.pageSize, $scope.connectionPagingOptions.currentPage); |
| } |
| }, true); |
| |
| $scope.totalConnections = 0; |
| $scope.pagedConnectionsData = [] |
| $scope.allConnectionFields = [] |
| $scope.allConnectionSelections = []; |
| $scope.allConnectionGrid = { |
| saveKey: 'allConnGrid', |
| data: 'pagedConnectionsData', |
| 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' |
| }, |
| ], |
| enablePaging: true, |
| showFooter: $scope.totalConnections > 50, |
| totalServerItems: 'totalConnections', |
| pagingOptions: $scope.connectionPagingOptions, |
| enableColumnResize: true, |
| multiSelect: false, |
| selectedItems: $scope.allConnectionSelections, |
| plugins: [new ngGridFlexibleHeightPlugin()], |
| afterSelectionChange: function(data) { |
| if (data.selected) { |
| var selItem = $scope.allConnectionSelections[0] |
| var nodeId = selItem.uid |
| // activate Routers->nodeId in the tree |
| $("#overtree").dynatree("getTree").activateKey(nodeId); |
| } |
| } |
| }; |
| // get info for a all connections |
| var allConnectionInfo = function () { |
| getAllConnectionFields([updateConnectionGrid, updateConnectionTree, scheduleNextUpdate]) |
| loadColState($scope.allConnectionGrid); |
| } |
| // called after conection data is available |
| var updateConnectionGrid = function (connectionFields) { |
| $scope.allConnectionFields = connectionFields; |
| getConnectionPagedData($scope.connectionPagingOptions.pageSize, $scope.connectionPagingOptions.currentPage); |
| } |
| |
| // get the connection data for all nodes |
| // called periodically |
| // creates a connectionFields array and calls the callbacks (updateTree and updateGrid) |
| var getAllConnectionFields = function (callbacks) { |
| var nodeIds = QDRService.nodeIdList() |
| var connectionFields = []; |
| var expected = nodeIds.length; |
| var received = 0; |
| var gotConnectionInfo = 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") |
| var connField = { |
| host: host, |
| security: sec, |
| authentication: auth, |
| routerId: nodeName, |
| uid: host + QDRService.valFor(response.attributeNames, result, "identity") |
| } |
| response.attributeNames.forEach( function (attribute, i) { |
| connField[attribute] = result[i] |
| }) |
| connectionFields.push(connField) |
| }) |
| if (expected === ++received) { |
| connectionFields.sort ( function (a,b) { return a.host < b.host ? -1 : a.host > b.host ? 1 : 0}) |
| callbacks.forEach( function (cb) { |
| cb(connectionFields) |
| }) |
| } |
| } |
| nodeIds.forEach( function (nodeId) { |
| QDRService.fetchEntity(nodeId, ".connection", [], gotConnectionInfo) |
| }) |
| } |
| |
| $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) { |
| $scope.address = address |
| var currentEntity = getCurrentLinksEntity(); |
| // we are viewing the addressLinks page |
| if (currentEntity === 'Address' && entityModes[currentEntity].currentModeId === 'links') { |
| updateModeLinks() |
| scheduleNextUpdate() |
| return; |
| } |
| |
| $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]}) |
| }) |
| scheduleNextUpdate() |
| 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) { |
| QDR.log.debug("linkInfo called for " + link.data.key) |
| if (!link) { |
| return; |
| } |
| $scope.link = link |
| |
| $scope.singleLinkFields = []; |
| var fields = Object.keys(link.data.fields) |
| var excludeFields = ["title", "uid", "uncounts", "rawDeliveryCount", "timestamp", "rawAddress"] |
| fields.forEach( function (field) { |
| if (excludeFields.indexOf(field) == -1) |
| $scope.singleLinkFields.push({attribute: field, value: link.data.fields[field]}) |
| }) |
| scheduleNextUpdate() |
| loadColState($scope.linkGrid); |
| } |
| |
| // get info for a single connection |
| $scope.gridModes = [{ |
| content: '<a><i class="icon-list"></i> Attributes</a>', |
| id: 'attributes', |
| title: "View attributes" |
| }, |
| { |
| content: '<a><i class="icon-link"></i> Links</a>', |
| id: 'links', |
| title: "Show links" |
| } |
| ]; |
| var saveModeIds = function () { |
| var modeIds = {Address: entityModes.Address.currentModeId, Connection: entityModes.Connection.currentModeId} |
| localStorage[OVERVIEWMODEIDS] = JSON.stringify(modeIds) |
| } |
| var loadModeIds = function () { |
| return angular.fromJson(localStorage[OVERVIEWMODEIDS]) || |
| {Address: 'attributes', Connection: 'attributes'} |
| } |
| var savedModeIds = loadModeIds() |
| var entityModes = { |
| Address: { |
| currentModeId: savedModeIds.Address, |
| filter: function (response, result) { |
| var owningAddr = QDRService.valFor(response.attributeNames, result, "owningAddr") |
| var id = $scope.address.data.fields.uid |
| return (owningAddr === $scope.address.data.fields.uid) |
| } |
| }, |
| Connection: { |
| currentModeId: savedModeIds.Connection, |
| filter: function (response, result) { |
| var connectionId = QDRService.valFor(response.attributeNames, result, "connectionId") |
| return (connectionId === $scope.connection.data.fields.identity) |
| } |
| } |
| } |
| $scope.selectMode = function (mode, entity) { |
| if (!mode || !entity) |
| return; |
| entityModes[entity].currentModeId = mode.id; |
| saveModeIds(); |
| if (mode.id === 'links') { |
| QDR.log.debug("setting linkFields to [] in selectMode") |
| $scope.linkFields = []; |
| getLinkPagedData($scope.linkPagingOptions.pageSize, $scope.linkPagingOptions.currentPage); |
| updateModeLinks(); |
| } |
| } |
| $scope.isModeSelected = function (mode, entity) { |
| return mode.id === entityModes[entity].currentModeId |
| } |
| $scope.isModeVisible = function (entity, id) { |
| return entityModes[entity].currentModeId === id |
| } |
| |
| var updateEntityLinkGrid = function (linkFields) { |
| $timeout(function () { |
| QDR.log.debug("setting linkFields in updateEntityLinkGrid"); |
| $scope.linkFields = linkFields |
| getLinkPagedData($scope.linkPagingOptions.pageSize, $scope.linkPagingOptions.currentPage); |
| }) |
| } |
| // based on which entity is selected, get and filter the links |
| var updateModeLinks = function () { |
| var currentEntity = getCurrentLinksEntity() |
| if (!currentEntity) |
| return; |
| var selectionCallback = entityModes[currentEntity].filter; |
| getAllLinkFields([updateEntityLinkGrid], selectionCallback) |
| } |
| var getCurrentLinksEntity = function () { |
| var currentEntity; |
| var active = $("#overtree").dynatree("getActiveNode"); |
| if (active) { |
| currentEntity = active.data.type; |
| } |
| return currentEntity; |
| } |
| |
| $scope.quiesceLinkClass = function (row) { |
| var stateClassMap = { |
| enabled: 'btn-primary', |
| disabled: 'btn-danger' |
| } |
| return stateClassMap[row.entity.adminStatus] |
| } |
| |
| $scope.quiesceLink = function (row, $event) { |
| QDRService.quiesceLink(row.entity.nodeId, row.entity.name); |
| $event.stopPropagation() |
| } |
| |
| $scope.quiesceLinkDisabled = function (row) { |
| return (row.entity.operStatus !== 'up' && row.entity.operStatus !== 'down') |
| } |
| $scope.quiesceLinkText = function (row) { |
| return row.entity.adminStatus === 'disabled' ? "Revive" : "Quiesce"; |
| } |
| |
| $scope.expandAll = function () { |
| $("#overtree").dynatree("getRoot").visit(function(node){ |
| node.expand(true); |
| }); |
| } |
| $scope.contractAll = function () { |
| $("#overtree").dynatree("getRoot").visit(function(node){ |
| node.expand(false); |
| }) |
| } |
| $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) { |
| if (!connection) |
| return; |
| $scope.connection = connection |
| |
| var currentEntity = getCurrentLinksEntity(); |
| // we are viewing the connectionLinks page |
| if (currentEntity === 'Connection' && entityModes[currentEntity].currentModeId === 'links') { |
| updateModeLinks() |
| scheduleNextUpdate() |
| return; |
| } |
| |
| $scope.connectionFields = []; |
| var fields = Object.keys(connection.data.fields) |
| fields.forEach( function (field) { |
| if (field != "title" && field != "uid") |
| $scope.connectionFields.push({attribute: field, value: connection.data.fields[field]}) |
| }) |
| // this is missing an argument? |
| loadColState($scope.connectionGrid); |
| } |
| |
| |
| var logModuleCellTemplate = '<div ng-click="logInfoFor(row, col)" class="ngCellText" ng-class="col.colIndex()"><span ng-cell-text>{{COL_FIELD | pretty}}</span></div>' |
| $scope.logModule = {} |
| $scope.logModuleSelected = [] |
| $scope.logModuleData = [] |
| $scope.logModuleGrid = { |
| data: 'logModuleData', |
| columnDefs: [ |
| { |
| field: 'nodeName', |
| displayName: 'Router', |
| }, |
| { |
| field: 'enable', |
| displayName: 'Enable level', |
| }, |
| { |
| field: 'noticeCount', |
| displayName: 'Notice', |
| cellTemplate: logModuleCellTemplate, |
| cellClass: 'grid-align-value', |
| }, |
| { |
| field: 'infoCount', |
| displayName: 'Info', |
| cellTemplate: logModuleCellTemplate, |
| cellClass: 'grid-align-value', |
| }, |
| { |
| field: 'traceCount', |
| displayName: 'Trace', |
| cellTemplate: logModuleCellTemplate, |
| cellClass: 'grid-align-value', |
| }, |
| { |
| field: 'debugCount', |
| displayName: 'Debug', |
| cellTemplate: logModuleCellTemplate, |
| cellClass: 'grid-align-value', |
| }, |
| { |
| field: 'warningCount', |
| displayName: 'Warning', |
| cellTemplate: logModuleCellTemplate, |
| cellClass: 'grid-align-value', |
| }, |
| { |
| field: 'errorCount', |
| displayName: 'Error', |
| cellTemplate: logModuleCellTemplate, |
| cellClass: 'grid-align-value', |
| }, |
| { |
| field: 'criticalCount', |
| displayName: 'Critical', |
| cellTemplate: logModuleCellTemplate, |
| cellClass: 'grid-align-value', |
| }, |
| ], |
| enableColumnResize: true, |
| multiSelect: false, |
| selectedItems: $scope.logModuleSelected, |
| plugins: [new ngGridFlexibleHeightPlugin()], |
| afterSelectionChange: function(data) { |
| if (data.selected) { |
| var selItem = $scope.logModuleSelected[0] |
| var nodeId = selItem.nodeId |
| |
| } |
| } |
| } |
| |
| $scope.logInfoFor = function (row, col) { |
| logDialog(row, col) |
| } |
| |
| function logDialog(row, col) { |
| var d = $uibModal.open({ |
| animation: true, |
| templateUrl: 'viewLogs.html', |
| controller: 'QDR.OverviewLogsController', |
| resolve: { |
| nodeName: function () { |
| return row.entity.nodeName |
| }, |
| module: function () { |
| return row.entity.name |
| }, |
| level: function () { |
| return col.displayName |
| }, |
| nodeId: function () { |
| return row.entity.nodeId |
| }, |
| } |
| }); |
| |
| d.result.then(function (result) { |
| console.log("d.open().then"); |
| }, function () { |
| console.log('Modal dismissed at: ' + new Date()); |
| }); |
| }; |
| |
| var numberTemplate = '<div class="ngCellText" ng-class="col.colIndex()"><span ng-cell-text>{{COL_FIELD | pretty}}</span></div>' |
| $scope.allLogFields = [] |
| $scope.allLogSelections = []; |
| $scope.allLogGrid = { |
| saveKey: 'allLogGrid', |
| data: 'allLogFields', |
| columnDefs: [ |
| { |
| field: 'name', |
| saveKey: 'allLogGrid', |
| displayName: 'Module' |
| }, |
| /* { |
| field: 'enable', |
| displayName: 'Enable' |
| }, |
| */ |
| |
| { |
| field: 'noticeCount', |
| displayName: 'Notice', |
| cellTemplate: numberTemplate, |
| cellClass: 'grid-align-value', |
| }, |
| { |
| field: 'infoCount', |
| displayName: 'Info', |
| cellTemplate: numberTemplate, |
| cellClass: 'grid-align-value', |
| }, |
| { |
| field: 'traceCount', |
| displayName: 'Trace', |
| cellTemplate: numberTemplate, |
| cellClass: 'grid-align-value', |
| }, |
| { |
| field: 'debugCount', |
| displayName: 'Debug', |
| cellTemplate: numberTemplate, |
| cellClass: 'grid-align-value', |
| }, |
| { |
| field: 'warningCount', |
| displayName: 'Warning', |
| cellTemplate: numberTemplate, |
| cellClass: 'grid-align-value', |
| }, |
| { |
| field: 'errorCount', |
| displayName: 'Error', |
| cellTemplate: numberTemplate, |
| cellClass: 'grid-align-value', |
| }, |
| { |
| field: 'criticalCount', |
| displayName: 'Critical', |
| cellTemplate: numberTemplate, |
| cellClass: 'grid-align-value', |
| }, |
| ], |
| //enableCellSelection: true, |
| enableColumnResize: true, |
| multiSelect: false, |
| selectedItems: $scope.allLogSelections, |
| plugins: [new ngGridFlexibleHeightPlugin()], |
| |
| afterSelectionChange: function(data) { |
| if (data.selected) { |
| var selItem = $scope.allLogSelections[0] |
| var nodeId = selItem.name |
| // activate in the tree |
| $("#overtree").dynatree("getTree").activateKey(nodeId); |
| } |
| } |
| |
| }; |
| |
| var allLogEntries = {} |
| var allLogInfo = function () { |
| // update the count of entries for each module |
| $scope.allLogFields = [] |
| var logResults = {} |
| var logDetails = {} |
| |
| var gotLogStats = function (node, entity, response) { |
| logDetails[node] = [] |
| response.results.forEach( function (result) { |
| var oresult = QDRService.flatten(response.attributeNames, result) |
| // make a copy for the details grid since logResults has the same object reference |
| logDetails[node].push(angular.copy(oresult)) |
| if (!(oresult.name in logResults)) { |
| logResults[oresult.name] = oresult |
| } |
| else { |
| response.attributeNames.forEach( function (attr, i) { |
| if (attr.substr(attr.length-5) === 'Count') { |
| logResults[oresult.name][attr] += result[i] |
| } |
| }) |
| } |
| }) |
| } |
| var gotAllLogStats = function () { |
| var sortedModules = Object.keys(logResults) |
| sortedModules.sort(function (a,b) {return a<b?-1:a>b?1:0}) |
| sortedModules.forEach( function (module) { |
| $scope.allLogFields.push(logResults[module]) |
| }) |
| allLogEntries = logDetails |
| updateLogTree($scope.allLogFields) |
| } |
| QDRService.fetchAllEntities({entity: 'logStats'}, gotAllLogStats, gotLogStats) |
| /* |
| var q = QDR.queue(1) |
| |
| var queuedSendMethod = function (node, callback) { |
| var gotLogInfo = function (nodeId, entity, response, context) { |
| var statusCode = context.message.application_properties.statusCode; |
| if (statusCode < 200 || statusCode >= 300) { |
| callback("getLog failed with statusCode of " + statusCode) |
| } else { |
| var logFields = response.map( function (result) { |
| return { |
| nodeId: QDRService.nameFromId(nodeId), |
| name: result[0], |
| type: result[1], |
| message: result[2], |
| source: result[3], |
| line: result[4], |
| time: Date(result[5]).toString() |
| } |
| }) |
| logResults.push.apply(logResults, logFields) // append new array to existing |
| callback(null) |
| } |
| } |
| QDRService.sendMethod(node, undefined, {}, "GET-LOG", {}, gotLogInfo) |
| } |
| for (var i=0; i<nodeIds.length; ++i) { |
| q.defer(queuedSendMethod, nodeIds[i]) |
| } |
| q.await(function (error) { |
| if (!error) { |
| logResults.sort( function (a, b) {return b.name - a.name}) |
| var allLogFields = $scope.allLogFields |
| $scope.allLogFields = []; |
| for (var i=0; i<allLogFields.length; ++i) { |
| $scope.allLogFields.push({module: allLogFields[i].module, |
| count: logResults.filter( function (entry) { |
| return entry.name === allLogFields[i].module |
| }).length |
| }) |
| } |
| $timeout(function () {allLogEntries = logResults; scheduleNextUpdate()}) |
| } |
| }) |
| } |
| if ($scope.allLogFields.length == 0) { |
| QDRService.fetchEntity(nodeIds[0], "logStats", [], function (nodeName, entity, response) { |
| var moduleIndex = response.attributeNames.indexOf("name") |
| response.results.sort( function (a,b) {return a[moduleIndex] < b[moduleIndex] ? -1 : a[moduleIndex] > b[moduleIndex] ? 1 : 0}) |
| response.results.forEach( function (result) { |
| var log = QDRService.flatten(response.attributeNames, result) |
| $scope.allLogFields.push(log) |
| }) |
| updateLogTree($scope.allLogFields) |
| haveLogFields() |
| }) |
| } else { |
| haveLogFields() |
| } |
| */ |
| } |
| |
| $scope.logFields = [] |
| // get info for a single log |
| var logInfo = function (node) { |
| |
| var gotLogInfo = function (responses) { |
| $timeout(function () { |
| $scope.logModuleData = [] |
| $scope.logModule.module = node.data.key |
| for (var n in responses) { |
| var moduleIndex = responses[n]['log'].attributeNames.indexOf("module") |
| var result = responses[n]['log'].results.filter( function (r) { |
| return r[moduleIndex] === node.data.key |
| })[0] |
| var logInfo = QDRService.flatten(responses[n]['log'].attributeNames, result) |
| var entry = allLogEntries[n] |
| entry.forEach( function (module) { |
| if (module.name === node.data.key) { |
| module.nodeName = QDRService.nameFromId(n) |
| module.nodeId = n |
| module.enable = logInfo.enable |
| $scope.logModuleData.push(module) |
| } |
| }) |
| } |
| $scope.logModuleData.sort ( function (a,b) { return a.nodeName < b.nodeName? -1 : a.nodeName> b.nodeName? 1 : 0}) |
| scheduleNextUpdate() |
| }) |
| } |
| QDRService.fetchAllEntities({entity: 'log', attrs: ['module', 'enable']}, gotLogInfo) |
| /* |
| $timeout(function () { |
| $scope.log = node |
| $scope.logFields = [] |
| for (var n in allLogEntries) { |
| var entry = allLogEntries[n] |
| entry.forEach( function (module) { |
| if (module.name === node.data.key) { |
| module.nodeId = n |
| $scope.logFields.push(module) |
| } |
| }) |
| } |
| scheduleNextUpdate() |
| }) |
| */ |
| } |
| |
| var getExpandedList = function () { |
| if (!treeRoot) |
| return; |
| var list = []; |
| if (treeRoot.visit) { |
| treeRoot.visit(function(node){ |
| if (node.isExpanded()) { |
| list.push(node.data.parent) |
| } |
| }); |
| } |
| return list; |
| } |
| |
| // 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) |
| expandedNodeList = list |
| } |
| |
| var setTemplate = function (node) { |
| var type = node.data.type; |
| var template = $scope.templates.filter( function (tpl) { |
| return tpl.name == type; |
| }) |
| $scope.template = template[0]; |
| } |
| $scope.template = $scope.templates[0] |
| // 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) |
| saveExpanded() |
| saveActivated(node.data.key) |
| |
| setTemplate(node) |
| // the nodes info function will fetch the grids data |
| if (node.data.info) { |
| $timeout(function () { |
| if (node.data.key === node.data.parent) { |
| node.data.info() |
| } |
| else { |
| node.data.info(node) |
| } |
| }) |
| } |
| } |
| |
| var treeNodeExpanded = function (node) { |
| saveExpanded() |
| tick() |
| } |
| $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 |
| var onDisconnect = function () { |
| QDR.log.info("we were just disconnected while on the overview page. Setting org to redirect back once we are connected again") |
| $timeout(function () { |
| QDRService.redirectWhenConnected("overview") |
| }) |
| } |
| QDRService.addDisconnectAction( onDisconnect ) |
| |
| /* -------------------------------------------------- |
| * |
| * 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.getNodeByKey(parentKey); |
| parentNode.removeChildren(); |
| |
| leaves.forEach( function (leaf) { |
| parentNode.addChild(worker(leaf)) |
| }) |
| scrollTree.scrollTop(scrollTop) |
| if (firstTime) { |
| var newActive = tree.getActiveNode(); |
| if (newActive && |
| // newActive.data.key === lastKey && |
| newActive.data.key !== newActive.data.parent && // this is a leaf node |
| newActive.data.parent === parentKey) { // the active node was just created |
| firstTime = false |
| QDR.log.debug("newly created node needs to be activated") |
| activated(newActive) |
| } |
| } |
| } |
| |
| // get saved tree state |
| var lastKey = loadActivatedNode(); |
| var expandedNodeList = loadExpandedNodeList(); |
| var firstTime = true; |
| |
| // 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" |
| routers.isFolder = true |
| 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; |
| } |
| $timeout(function () {updateLeaves(nodes, "Routers", routers, worker)}) |
| } |
| |
| // 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" |
| addresses.isFolder = true |
| 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.tooltip = address['class'] + " address" |
| if (address.address === '$management') |
| a.tooltip = "internal " + a.tooltip |
| a.addClass = a.tooltip |
| a.activate = lastKey === address.uid |
| a.parent = "Addresses" |
| return a; |
| } |
| $timeout(function () {updateLeaves(addressFields, "Addresses", addresses, worker)}) |
| } |
| |
| $scope.$watch("filter", function (newValue, oldValue) { |
| if (newValue !== oldValue) { |
| $timeout(allLinkInfo); |
| localStorage[FILTERKEY] = JSON.stringify($scope.filter) |
| } |
| }, true) |
| |
| $scope.filterToggle = function () { |
| var filter = $('#linkFilter') |
| filter.toggle(); |
| } |
| |
| $scope.filter = angular.fromJson(localStorage[FILTERKEY]) || {endpointsOnly: "true", hideConsoles: true}; |
| var links = new Folder("Links") |
| 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" |
| links.isFolder = true |
| 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) |
| var isConsole = QDRService.isConsoleLink(link) |
| l.info = linkInfo |
| l.key = link.uid |
| l.fields = link |
| l.type = "Link" |
| l.parent = "Links" |
| l.activate = lastKey === link.uid |
| if (isConsole) |
| l.tooltip = "console link" |
| else |
| l.tooltip = link.linkType + " link" |
| l.addClass = l.tooltip |
| return l; |
| } |
| $timeout(function () {updateLeaves(linkFields, "Links", links, worker)}) |
| } |
| |
| 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" |
| connections.isFolder = true |
| topLevelChildren.push(connections) |
| |
| updateConnectionTree = function (connectionFields) { |
| var worker = function (connection) { |
| var c = new Folder(connection.host) |
| var isConsole = QDRService.isAConsole (connection.properties, connection.identity, connection.role, connection.routerId) |
| c.type = "Connection" |
| c.info = connectionInfo |
| c.key = connection.uid |
| c.fields = connection |
| if (isConsole) |
| c.tooltip = "console connection" |
| else |
| c.tooltip = connection.role === "inter-router" ? "inter-router connection" : "external connection" |
| c.addClass = c.tooltip |
| c.parent = "Connections" |
| c.activate = lastKey === connection.uid |
| return c |
| } |
| $timeout(function () {updateLeaves(connectionFields, "Connections", connections, worker)}) |
| } |
| |
| var updateLogTree = function (logFields) { |
| var worker = function (log) { |
| var l = new Folder(log.name) |
| l.type = "Log" |
| l.info = logInfo |
| l.key = log.name |
| l.parent = "Logs" |
| l.activate = lastKey === l.key |
| l.addClass = "log" |
| return l |
| } |
| $timeout(function () {updateLeaves(logFields, "Logs", logs, worker)}) |
| } |
| |
| var htmlReady = false; |
| var dataReady = false; |
| $scope.largeNetwork = QDRService.isLargeNetwork() |
| 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" |
| logs.isFolder = true |
| if (QDRService.versionCheck('0.8.0')) |
| topLevelChildren.push(logs) |
| var initTreeAndGrid = function () { |
| if (!htmlReady || !dataReady) |
| return; |
| var div = angular.element("#overtree"); |
| if (!div.width()) { |
| setTimeout(initTreeAndGrid, 100); |
| return; |
| } |
| $('#overtree').dynatree({ |
| onActivate: activated, |
| onExpand: treeNodeExpanded, |
| autoCollapse: $scope.largeNetwork, |
| activeVisible: !$scope.largeNetwork, |
| selectMode: 1, |
| debugLevel: 0, |
| classNames: { |
| expander: 'fa-angle', |
| connector: 'dynatree-no-connector' |
| }, |
| children: topLevelChildren |
| }) |
| treeRoot = $("#overtree").dynatree("getRoot"); |
| tick() |
| 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.overviewLoaded = function () { |
| htmlReady = true; |
| initTreeAndGrid(); |
| } |
| |
| var nodeIds = QDRService.nodeIdList() |
| //updateRouterTree(nodeIds); |
| // add placeholders for the top level tree nodes |
| var topLevelTreeNodes = [routers, addresses, links, connections, logs] |
| topLevelTreeNodes.forEach( function (parent) { |
| var placeHolder = new Folder("loading...") |
| placeHolder.addClass = "loading" |
| parent.children = [placeHolder] |
| }) |
| |
| var singleQ = null |
| var updateExpanded = function () { |
| if (!treeRoot) |
| return; |
| if (treeRoot.visit) { |
| treeRoot.visit(function(node){ |
| if (node.isActive()) |
| setTemplate(node) |
| if (node.isActive() || node.isExpanded()) { |
| if (node.data.key === node.data.parent) { |
| node.data.info() |
| } |
| else { |
| node.data.info(node) |
| } |
| } |
| }) |
| } |
| } |
| |
| var tickTimer; |
| var scheduleNextUpdate = function () { |
| clearTimeout(tickTimer) |
| tickTimer = setTimeout(tick, refreshInterval) |
| } |
| var tick = function () { |
| clearTimeout(tickTimer) |
| updateExpanded(); |
| } |
| dataReady = true; |
| initTreeAndGrid(); |
| $scope.$on("$destroy", function( event ) { |
| clearTimeout(tickTimer) |
| QDRService.delDisconnectAction( onDisconnect ) |
| //QDRService.stopUpdating() |
| }); |
| |
| }]); |
| |
| return QDR; |
| |
| }(QDR || {})); |