Vitrage - entity graph fixes:
============================= 1. Circles on entity graph are bigger 2. Alarms fixed - now shown on graph 3. Heat Stack icon added 4. Captions in entities info panel fixed. 5. Info Panel style fixed 6. Heat stack filter added 7. Heat stack - Depth of graph added 8. Bug - data change was checked just by number of nodes. Now it also check names Change-Id: I4af0863a5e217ec3435dccce3b75d1a7e05ac4e0
This commit is contained in:
parent
8be5a32a61
commit
e3caa58f24
@ -12,6 +12,16 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
"""
|
||||||
|
https://docs.openstack.org/horizon/latest/contributor/tutorials/plugin.html
|
||||||
|
"""
|
||||||
|
|
||||||
|
""" This file will likely be necessary if creating a Django or Angular driven
|
||||||
|
plugin. This file is intended to act as a convenient location for
|
||||||
|
interacting with the new service this plugin is supporting.
|
||||||
|
While interactions with the service can be handled in the views.py,
|
||||||
|
isolating the logic is an established pattern in Horizon.
|
||||||
|
"""
|
||||||
|
|
||||||
from horizon.utils.memoized import memoized # noqa
|
from horizon.utils.memoized import memoized # noqa
|
||||||
from keystoneauth1.identity.generic.token import Token
|
from keystoneauth1.identity.generic.token import Token
|
||||||
@ -19,6 +29,9 @@ from keystoneauth1.session import Session
|
|||||||
from openstack_dashboard.api import base
|
from openstack_dashboard.api import base
|
||||||
from vitrageclient import client as vitrage_client
|
from vitrageclient import client as vitrage_client
|
||||||
|
|
||||||
|
import logging
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@memoized
|
@memoized
|
||||||
def vitrageclient(request, password=None):
|
def vitrageclient(request, password=None):
|
||||||
@ -30,10 +43,19 @@ def vitrageclient(request, password=None):
|
|||||||
return vitrage_client.Client('1', session)
|
return vitrage_client.Client('1', session)
|
||||||
|
|
||||||
|
|
||||||
def topology(request, query=None, graph_type='tree', all_tenants='false'):
|
def topology(request, query=None, graph_type='tree', all_tenants='false',
|
||||||
|
root=None, limit=None):
|
||||||
|
LOG.info("--------- CALLING VITRAGE_CLIENT ---request %s", str(request))
|
||||||
|
LOG.info("--------- CALLING VITRAGE_CLIENT ---query %s", str(query))
|
||||||
|
LOG.info("------ CALLING VITRAGE_CLIENT --graph_type %s", str(graph_type))
|
||||||
|
LOG.info("---- CALLING VITRAGE_CLIENT --all_tenants %s", str(all_tenants))
|
||||||
|
LOG.info("--------- CALLING VITRAGE_CLIENT --------root %s", str(root))
|
||||||
|
LOG.info("--------- CALLING VITRAGE_CLIENT --------limit %s", str(limit))
|
||||||
return vitrageclient(request).topology.get(query=query,
|
return vitrageclient(request).topology.get(query=query,
|
||||||
graph_type=graph_type,
|
graph_type=graph_type,
|
||||||
all_tenants=all_tenants)
|
all_tenants=all_tenants,
|
||||||
|
root=root,
|
||||||
|
limit=limit)
|
||||||
|
|
||||||
|
|
||||||
def alarms(request, vitrage_id='all', all_tenants='false'):
|
def alarms(request, vitrage_id='all', all_tenants='false'):
|
||||||
|
@ -12,16 +12,14 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
|
||||||
from django.views import generic
|
from django.views import generic
|
||||||
|
import logging
|
||||||
|
|
||||||
from openstack_dashboard.api.rest import utils as rest_utils
|
|
||||||
|
|
||||||
from openstack_dashboard.api.rest import urls
|
from openstack_dashboard.api.rest import urls
|
||||||
|
from openstack_dashboard.api.rest import utils as rest_utils
|
||||||
from vitrage_dashboard.api import vitrage
|
from vitrage_dashboard.api import vitrage
|
||||||
|
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@urls.register
|
@urls.register
|
||||||
class Topolgy(generic.View):
|
class Topolgy(generic.View):
|
||||||
@ -41,16 +39,27 @@ class Topolgy(generic.View):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
''' original default is graph '''
|
''' original default is graph '''
|
||||||
|
|
||||||
|
LOG.info("--------- reques --------------- %s", str(request))
|
||||||
|
|
||||||
graph_type = 'tree'
|
graph_type = 'tree'
|
||||||
all_tenants = 'false'
|
all_tenants = 'false'
|
||||||
|
root = None
|
||||||
|
limit = None
|
||||||
|
|
||||||
if 'graph_type' in request.GET:
|
if 'graph_type' in request.GET:
|
||||||
graph_type = request.GET.get('graph_type')
|
graph_type = request.GET.get('graph_type')
|
||||||
if 'all_tenants' in request.GET:
|
if 'all_tenants' in request.GET:
|
||||||
all_tenants = request.GET.get('all_tenants')
|
all_tenants = request.GET.get('all_tenants')
|
||||||
|
if 'root' in request.GET:
|
||||||
|
root = request.GET.get('root')
|
||||||
|
if 'depth' in request.GET:
|
||||||
|
limit = int(request.GET.get('depth'))
|
||||||
|
|
||||||
query = None
|
query = None
|
||||||
if 'query' in request.GET:
|
if 'query' in request.GET:
|
||||||
query = request.GET.get('query')
|
query = request.GET.get('query')
|
||||||
|
LOG.info("--A request QUERY -- %s", str(query))
|
||||||
elif graph_type == 'tree':
|
elif graph_type == 'tree':
|
||||||
''' Default tree query - get computes, used by Sunburst'''
|
''' Default tree query - get computes, used by Sunburst'''
|
||||||
query = '{"and": [{"==": {"vitrage_category": "RESOURCE"}},' \
|
query = '{"and": [{"==": {"vitrage_category": "RESOURCE"}},' \
|
||||||
@ -64,7 +73,9 @@ class Topolgy(generic.View):
|
|||||||
return vitrage.topology(request=request,
|
return vitrage.topology(request=request,
|
||||||
query=query,
|
query=query,
|
||||||
graph_type=graph_type,
|
graph_type=graph_type,
|
||||||
all_tenants=all_tenants)
|
all_tenants=all_tenants,
|
||||||
|
root=root,
|
||||||
|
limit=limit)
|
||||||
|
|
||||||
|
|
||||||
@urls.register
|
@urls.register
|
||||||
|
@ -30,12 +30,13 @@
|
|||||||
config = config || {};
|
config = config || {};
|
||||||
|
|
||||||
if (graph_type) {
|
if (graph_type) {
|
||||||
config.params = {graph_type: graph_type};
|
config.params = config.params || {};
|
||||||
|
config.params.graph_type = graph_type;
|
||||||
}
|
}
|
||||||
if (admin){
|
if (admin){
|
||||||
(!config.params) ? config.params = {all_tenants: true} : config.params.all_tenants = true;
|
(!config.params) ? config.params = {all_tenants: true} : config.params.all_tenants = true;
|
||||||
}
|
}
|
||||||
|
console.info('CONFIG in core - ', config)
|
||||||
return apiService.get('/api/vitrage/topology/', config)
|
return apiService.get('/api/vitrage/topology/', config)
|
||||||
.error(function () {
|
.error(function () {
|
||||||
toastService.add('error', gettext('Unable to fetch the Vitrage Topology service.'));
|
toastService.add('error', gettext('Unable to fetch the Vitrage Topology service.'));
|
||||||
|
@ -1,265 +1,342 @@
|
|||||||
(function() {
|
(function () {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
angular
|
angular
|
||||||
.module('horizon.dashboard.project.vitrage')
|
.module('horizon.dashboard.project.vitrage')
|
||||||
.controller('EntitiesController', EntitiesController);
|
.controller('EntitiesController', EntitiesController);
|
||||||
|
|
||||||
EntitiesController.$inject = ['$scope', 'vitrageTopologySrv', '$interval', '$location'];
|
EntitiesController.$inject = ['$scope', 'vitrageTopologySrv', '$interval', '$location', '$timeout'];
|
||||||
|
|
||||||
function EntitiesController($scope, vitrageTopologySrv, $interval, $location) {
|
function EntitiesController($scope, vitrageTopologySrv, $interval, $location, $timeout) {
|
||||||
this.model = {selected: {}};
|
this.model = {selected: {}};
|
||||||
|
|
||||||
var _this = this,
|
var _this = this,
|
||||||
loadTime = 5000,
|
loadTime = 5000,
|
||||||
errorCount = 0,
|
errorCount = 0,
|
||||||
loadInterval;
|
loadInterval,
|
||||||
|
initialized = false,
|
||||||
|
timeoutSubscriber;
|
||||||
|
|
||||||
|
|
||||||
$scope.$watch('automaticRefresh', function(newData, oldData) {
|
$scope.$watch('automaticRefresh', function (newData, oldData) {
|
||||||
if (newData !== undefined && newData != oldData) {
|
if (newData !== undefined && newData != oldData) {
|
||||||
horizon.cookies.put('entitiesAutomaticRefresh', newData);
|
horizon.cookies.put('entitiesAutomaticRefresh', newData);
|
||||||
if (newData) {
|
if (newData) {
|
||||||
nextLoad();
|
nextLoad();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
$scope.$on('graphItemClicked', function(event, data) {
|
|
||||||
_this.selectedItem = data;
|
|
||||||
event.stopPropagation();
|
|
||||||
$scope.$digest();
|
|
||||||
});
|
|
||||||
|
|
||||||
this.setSelected = function(item) {
|
|
||||||
this.model.selected = item;
|
|
||||||
};
|
|
||||||
|
|
||||||
loadData();
|
|
||||||
|
|
||||||
function loadData() {
|
|
||||||
var url = $location.absUrl();
|
|
||||||
var admin = false;
|
|
||||||
|
|
||||||
if (url.indexOf('admin') != -1) admin = true;
|
|
||||||
|
|
||||||
vitrageTopologySrv.getTopology('graph', null, admin)
|
|
||||||
.then(function(res) {
|
|
||||||
var nodes = res.data.nodes,
|
|
||||||
links = res.data.links;
|
|
||||||
|
|
||||||
_.each(links, function(link) {
|
|
||||||
link.source = nodes[link.source];
|
|
||||||
link.target = nodes[link.target];
|
|
||||||
});
|
|
||||||
|
|
||||||
if (_this.graphData) {
|
|
||||||
mergeData(res.data);
|
|
||||||
} else {
|
|
||||||
_this.graphData = res.data;
|
|
||||||
_this.graphData.ts = Date.now();
|
|
||||||
}
|
|
||||||
|
|
||||||
errorCount = 0;
|
|
||||||
nextLoad();
|
|
||||||
})
|
|
||||||
.catch(function(res) {
|
|
||||||
nextLoad(++errorCount * 2 * loadTime);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function nextLoad(mill) {
|
|
||||||
mill = mill || loadTime;
|
|
||||||
cancelNextLoad();
|
|
||||||
|
|
||||||
if ($scope.automaticRefresh) {
|
|
||||||
loadInterval = $interval(loadData, mill);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function cancelNextLoad() {
|
|
||||||
$interval.cancel(loadInterval);
|
|
||||||
}
|
|
||||||
|
|
||||||
function mergeData(data) {
|
|
||||||
var graphNodes = $scope.vm.graphData.nodes,
|
|
||||||
graphLinks = $scope.vm.graphData.links;
|
|
||||||
|
|
||||||
if (graphNodes.length != data.nodes.length || graphLinks.length != data.links.length) {
|
|
||||||
graphNodes.splice(0, graphNodes.length);
|
|
||||||
graphLinks.splice(0, graphLinks.length);
|
|
||||||
|
|
||||||
_.each(data.nodes, function(node) {
|
|
||||||
graphNodes.push(node);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
_.each(data.links, function(link) {
|
$scope.$watch('selectedHeat', function (newData, oldData) {
|
||||||
graphLinks.push(link);
|
if (newData !== undefined && newData != oldData) {
|
||||||
|
if (timeoutSubscriber) {
|
||||||
|
console.log('Canceling heat stack timeout');
|
||||||
|
$timeout.cancel(timeoutSubscriber);
|
||||||
|
}
|
||||||
|
timeoutSubscriber = $timeout(loadData, 250);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$scope.vm.graphData.ts = Date.now();
|
$scope.$watch('depthRange', function (newData, oldData) {
|
||||||
|
if (newData !== undefined && newData != oldData) {
|
||||||
/* temp stuff */
|
if (timeoutSubscriber) {
|
||||||
d3.selectAll('.node .icon')
|
console.log('Canceling depth timeout');
|
||||||
.attr('text-anchor', 'middle')
|
$timeout.cancel(timeoutSubscriber);
|
||||||
.attr('dominant-baseline', 'central')
|
|
||||||
.attr('transform', 'scale(1)')
|
|
||||||
.attr('class', function(d) {
|
|
||||||
var category = d.category,
|
|
||||||
cls = '';
|
|
||||||
if (category && category.toLowerCase() === 'alarm') {
|
|
||||||
var severity = d.vitrage_operational_severity;
|
|
||||||
if (severity) {
|
|
||||||
switch (severity.toLowerCase()) {
|
|
||||||
case 'critical':
|
|
||||||
cls = 'red';
|
|
||||||
break;
|
|
||||||
case 'severe':
|
|
||||||
cls = 'orange';
|
|
||||||
break;
|
|
||||||
case 'warning':
|
|
||||||
cls = 'yellow';
|
|
||||||
break;
|
|
||||||
case 'ok':
|
|
||||||
cls = 'green';
|
|
||||||
break;
|
|
||||||
case 'n/a':
|
|
||||||
cls = 'gray';
|
|
||||||
break;
|
|
||||||
default: //'DISABLED', 'UNKNOWN', 'UNDEFINED'
|
|
||||||
cls = 'gray';
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
timeoutSubscriber = $timeout(loadData, 250);
|
||||||
} else {
|
}
|
||||||
var reald = _.find(graphNodes, function(n) {
|
});
|
||||||
return n.id == d.id;
|
|
||||||
});
|
|
||||||
|
|
||||||
var state = reald.vitrage_operational_state;
|
$scope.$on('graphItemClicked', function (event, data) {
|
||||||
if (state) {
|
_this.selectedItem = data;
|
||||||
switch (state.toLowerCase()) {
|
event.stopPropagation();
|
||||||
case 'error':
|
$scope.$digest();
|
||||||
cls = 'red';
|
});
|
||||||
break;
|
|
||||||
case 'suboptimal':
|
|
||||||
cls = 'yellow';
|
|
||||||
break;
|
|
||||||
case 'n/a':
|
|
||||||
cls = 'gray';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return cls;
|
|
||||||
})
|
|
||||||
.style('font-size', function(d) {
|
|
||||||
var category = d.category || 'no_category',
|
|
||||||
icon_size;
|
|
||||||
|
|
||||||
if (category && category.toLowerCase() === 'alarm') {
|
this.setSelected = function (item) {
|
||||||
icon_size = '18px';
|
this.model.selected = item;
|
||||||
} else {
|
};
|
||||||
var type = d.vitrage_type || 'no_type';
|
|
||||||
switch (type.toLowerCase()) {
|
|
||||||
case 'nova.instance':
|
|
||||||
case 'nova.host':
|
|
||||||
case 'nova.zone':
|
|
||||||
case 'neutron.port':
|
|
||||||
icon_size = '16px'; //fa-external-link-square
|
|
||||||
break;
|
|
||||||
case 'openstack.cluster':
|
|
||||||
icon_size = '18px'; //fa-cloud
|
|
||||||
break;
|
|
||||||
case 'cinder.volume':
|
|
||||||
icon_size = '22px';
|
|
||||||
break;
|
|
||||||
case 'neutron.network':
|
|
||||||
default:
|
|
||||||
icon_size = '20px';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return icon_size;
|
|
||||||
})
|
|
||||||
.style('stroke', function(d) {
|
|
||||||
var category = d.category;
|
|
||||||
if (category && category.toLowerCase() === 'alarm') {
|
|
||||||
return '18px'
|
|
||||||
}
|
|
||||||
return '20px'
|
|
||||||
})
|
|
||||||
.classed('icon', true)
|
|
||||||
.classed('fill-only', function(d) {
|
|
||||||
var type = (d.vitrage_type || '').toLowerCase();
|
|
||||||
if (type && type === 'nova.host' || type === 'cinder.volume') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.text(function(d) {
|
|
||||||
var category = d.category,
|
|
||||||
icon;
|
|
||||||
if (category && category.toLowerCase() === 'alarm') {
|
|
||||||
icon = '\uf0f3'; //\uf0a2'; //bell-o
|
|
||||||
} else {
|
|
||||||
var type = d.vitrage_type || 'no_type';
|
|
||||||
switch (type.toLowerCase()) {
|
|
||||||
case 'nova.instance':
|
|
||||||
icon = '\uf108'; //fa-desktop
|
|
||||||
break;
|
|
||||||
case 'nova.host':
|
|
||||||
icon = '\uf233'; //fa-server
|
|
||||||
break;
|
|
||||||
case 'nova.zone':
|
|
||||||
icon = '\uf279'; //fa-map
|
|
||||||
break;
|
|
||||||
case 'neutron.network':
|
|
||||||
icon = '\uf0ac'; //fa-globe
|
|
||||||
break;
|
|
||||||
case 'neutron.port':
|
|
||||||
icon = '\uf14c'; //fa-external-link-square
|
|
||||||
break;
|
|
||||||
case 'cinder.volume':
|
|
||||||
icon = '\uf0a0'; //fa-hdd-o
|
|
||||||
break;
|
|
||||||
case 'openstack.cluster':
|
|
||||||
icon = '\uf0c2'; //fa-cloud
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
icon = '\uf013'; //fa-cog
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return icon
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// we need to updated the selected info
|
loadData();
|
||||||
if (_this.selectedItem && _this.selectedItem.vitrage_id && _this.selectedItem.vitrage_id !== '') {
|
|
||||||
for (var i = 0; i < data.nodes.length; i++) {
|
function loadData() {
|
||||||
var val = data.nodes[i];
|
var url = $location.absUrl();
|
||||||
if (val && val.vitrage_id && val.vitrage_id == _this.selectedItem.vitrage_id) {
|
var admin = false;
|
||||||
_this.selectedItem = val;
|
if (url.indexOf('admin') != -1) admin = true;
|
||||||
break;
|
|
||||||
}
|
// get heat stacks
|
||||||
|
if (!_this.initialized) {
|
||||||
|
vitrageTopologySrv.getTopology('graph', null, admin)
|
||||||
|
.then(function (res) {
|
||||||
|
var heats = [];
|
||||||
|
|
||||||
|
_.each(res.data.nodes, function (node) {
|
||||||
|
if (node.vitrage_type === 'heat.stack') {
|
||||||
|
heats.push({name: node.name, vitrageId: node.vitrage_id});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$scope.heats = heats;
|
||||||
|
_this.initialized = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var config = {params: {query: '{"==": {"vitrage_is_deleted" : false} }'}};
|
||||||
|
if ($scope.selectedHeat && $scope.selectedHeat !== 'all') {
|
||||||
|
config.params.depth = $scope.depthRange;
|
||||||
|
config.params.root = $scope.selectedHeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Config: ', config);
|
||||||
|
|
||||||
|
vitrageTopologySrv.getTopology('graph', config, admin)
|
||||||
|
.then(function (res) {
|
||||||
|
var nodes = res.data.nodes,
|
||||||
|
links = res.data.links;
|
||||||
|
|
||||||
|
_.each(links, function (link) {
|
||||||
|
link.source = nodes[link.source];
|
||||||
|
link.target = nodes[link.target];
|
||||||
|
});
|
||||||
|
|
||||||
|
if (_this.graphData) {
|
||||||
|
mergeData(res.data);
|
||||||
|
} else {
|
||||||
|
_this.graphData = res.data;
|
||||||
|
_this.graphData.ts = Date.now();
|
||||||
|
}
|
||||||
|
|
||||||
|
errorCount = 0;
|
||||||
|
nextLoad();
|
||||||
|
})
|
||||||
|
.catch(function (res) {
|
||||||
|
nextLoad(++errorCount * 2 * loadTime);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* utils */
|
function nextLoad(mill) {
|
||||||
function rnd(min, max) {
|
mill = mill || loadTime;
|
||||||
return Math.round(Math.random() * (max - min)) + min;
|
cancelNextLoad();
|
||||||
}
|
|
||||||
|
|
||||||
function onlyIn(a1, a2, prop) {
|
if ($scope.automaticRefresh) {
|
||||||
prop = prop || 'id';
|
loadInterval = $interval(loadData, mill);
|
||||||
return a1.filter(function(o1) {
|
}
|
||||||
return a2.filter(function(o2) {
|
|
||||||
return o1[prop] === o2[prop];
|
}
|
||||||
}).length === 0;
|
|
||||||
})
|
function cancelNextLoad() {
|
||||||
|
$interval.cancel(loadInterval);
|
||||||
|
}
|
||||||
|
|
||||||
|
function dataChanged(nodes1, nodes2, links1, links2) {
|
||||||
|
if (nodes1.length !== nodes2.length || links1.length !== links2.length) {
|
||||||
|
console.log('number of nodes or links changed');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for nodes change
|
||||||
|
for (var i = 0; i < nodes1.length; i++) {
|
||||||
|
var nodeFound = false;
|
||||||
|
for (var j = 0; j < nodes2.length; j++) {
|
||||||
|
if (nodes1[i].name === nodes2[j].name) {
|
||||||
|
nodeFound = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!nodeFound) {
|
||||||
|
console.log('name of nodes changed');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function mergeData(data) {
|
||||||
|
var graphNodes = $scope.vm.graphData.nodes,
|
||||||
|
graphLinks = $scope.vm.graphData.links;
|
||||||
|
|
||||||
|
if (dataChanged(graphNodes, data.nodes, graphLinks, data.links)) {
|
||||||
|
graphNodes.splice(0, graphNodes.length);
|
||||||
|
graphLinks.splice(0, graphLinks.length);
|
||||||
|
|
||||||
|
_.each(data.nodes, function (node) {
|
||||||
|
graphNodes.push(node);
|
||||||
|
});
|
||||||
|
|
||||||
|
_.each(data.links, function (link) {
|
||||||
|
graphLinks.push(link);
|
||||||
|
});
|
||||||
|
|
||||||
|
$scope.vm.graphData.ts = Date.now();
|
||||||
|
|
||||||
|
/* temp stuff */
|
||||||
|
d3.selectAll('.node .icon')
|
||||||
|
.attr('text-anchor', 'middle')
|
||||||
|
.attr('dominant-baseline', 'central')
|
||||||
|
.attr('transform', 'scale(1)')
|
||||||
|
.attr('class', function (d) {
|
||||||
|
var category = d.category,
|
||||||
|
cls = '';
|
||||||
|
if (category && category.toLowerCase() === 'alarm') {
|
||||||
|
var severity = d.vitrage_operational_severity;
|
||||||
|
if (severity) {
|
||||||
|
switch (severity.toLowerCase()) {
|
||||||
|
case 'critical':
|
||||||
|
cls = 'red';
|
||||||
|
break;
|
||||||
|
case 'severe':
|
||||||
|
cls = 'orange';
|
||||||
|
break;
|
||||||
|
case 'warning':
|
||||||
|
cls = 'yellow';
|
||||||
|
break;
|
||||||
|
case 'ok':
|
||||||
|
cls = 'green';
|
||||||
|
break;
|
||||||
|
case 'n/a':
|
||||||
|
cls = 'gray';
|
||||||
|
break;
|
||||||
|
default: //'DISABLED', 'UNKNOWN', 'UNDEFINED'
|
||||||
|
cls = 'gray';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var reald = _.find(graphNodes, function (n) {
|
||||||
|
return n.id == d.id;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (reald) {
|
||||||
|
var state = reald.vitrage_operational_state;
|
||||||
|
if (state) {
|
||||||
|
switch (state.toLowerCase()) {
|
||||||
|
case 'error':
|
||||||
|
cls = 'red';
|
||||||
|
break;
|
||||||
|
case 'suboptimal':
|
||||||
|
cls = 'yellow';
|
||||||
|
break;
|
||||||
|
case 'n/a':
|
||||||
|
cls = 'gray';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cls;
|
||||||
|
})
|
||||||
|
.style('font-size', function (d) {
|
||||||
|
var category = d.category || 'no_category',
|
||||||
|
icon_size;
|
||||||
|
|
||||||
|
if (category && category.toLowerCase() === 'alarm') {
|
||||||
|
icon_size = '18px';
|
||||||
|
} else {
|
||||||
|
var type = d.vitrage_type || 'no_type';
|
||||||
|
switch (type.toLowerCase()) {
|
||||||
|
case 'nova.instance':
|
||||||
|
case 'nova.host':
|
||||||
|
case 'nova.zone':
|
||||||
|
case 'neutron.port':
|
||||||
|
icon_size = '16px'; //fa-external-link-square
|
||||||
|
break;
|
||||||
|
case 'openstack.cluster':
|
||||||
|
icon_size = '18px'; //fa-cloud
|
||||||
|
break;
|
||||||
|
case 'cinder.volume':
|
||||||
|
icon_size = '22px';
|
||||||
|
break;
|
||||||
|
case 'neutron.network':
|
||||||
|
default:
|
||||||
|
icon_size = '20px';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return icon_size;
|
||||||
|
})
|
||||||
|
.style('stroke', function (d) {
|
||||||
|
var category = d.category;
|
||||||
|
if (category && category.toLowerCase() === 'alarm') {
|
||||||
|
return '18px';
|
||||||
|
}
|
||||||
|
return '20px';
|
||||||
|
})
|
||||||
|
.classed('icon', true)
|
||||||
|
.classed('fill-only', function (d) {
|
||||||
|
var type = (d.vitrage_type || '').toLowerCase();
|
||||||
|
if (type && type === 'nova.host' || type === 'cinder.volume') {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.text(function (d) {
|
||||||
|
var category = d.category,
|
||||||
|
icon;
|
||||||
|
if (category && category.toLowerCase() === 'alarm') {
|
||||||
|
icon = '\uf0f3'; //\uf0a2'; //bell-o
|
||||||
|
} else {
|
||||||
|
var type = d.vitrage_type || 'no_type';
|
||||||
|
|
||||||
|
switch (type.toLowerCase()) {
|
||||||
|
case 'nova.instance':
|
||||||
|
icon = '\uf108'; //fa-desktop
|
||||||
|
break;
|
||||||
|
case 'nova.host':
|
||||||
|
icon = '\uf233'; //fa-server
|
||||||
|
break;
|
||||||
|
case 'nova.zone':
|
||||||
|
icon = '\uf279'; //fa-map
|
||||||
|
break;
|
||||||
|
case 'neutron.network':
|
||||||
|
icon = '\uf0ac'; //fa-globe
|
||||||
|
break;
|
||||||
|
case 'neutron.port':
|
||||||
|
icon = '\uf14c'; //fa-external-link-square
|
||||||
|
break;
|
||||||
|
case 'cinder.volume':
|
||||||
|
icon = '\uf0a0'; //fa-hdd-o
|
||||||
|
break;
|
||||||
|
case 'openstack.cluster':
|
||||||
|
icon = '\uf0c2'; //fa-cloud
|
||||||
|
break;
|
||||||
|
case 'heat.stack':
|
||||||
|
icon = '\uf1b3'; //fa-cubes
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
console.warn('Vitrage type not supported: ' + d.vitrage_type);
|
||||||
|
icon = '\uf1b3'; //fa-cog
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return icon;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// we need to updated the selected info
|
||||||
|
if (_this.selectedItem && _this.selectedItem.vitrage_id && _this.selectedItem.vitrage_id !== '') {
|
||||||
|
for (var i = 0; i < data.nodes.length; i++) {
|
||||||
|
var val = data.nodes[i];
|
||||||
|
if (val && val.vitrage_id && val.vitrage_id == _this.selectedItem.vitrage_id) {
|
||||||
|
_this.selectedItem = val;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* utils */
|
||||||
|
function rnd(min, max) {
|
||||||
|
return Math.round(Math.random() * (max - min)) + min;
|
||||||
|
}
|
||||||
|
|
||||||
|
function onlyIn(a1, a2, prop) {
|
||||||
|
prop = prop || 'id';
|
||||||
|
return a1.filter(function (o1) {
|
||||||
|
return a2.filter(function (o2) {
|
||||||
|
return o1[prop] === o2[prop];
|
||||||
|
}).length === 0;
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
})();
|
})();
|
@ -7,7 +7,11 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<hz-entities-info item="vm.selectedItem"></hz-entities-info>
|
<hz-entities-info item="vm.selectedItem"></hz-entities-info>
|
||||||
<hz-entities-toolbox search-text="searchText" auto-refresh="automaticRefresh"></hz-entities-toolbox>
|
<hz-entities-toolbox search-text="searchText"
|
||||||
|
auto-refresh="automaticRefresh"
|
||||||
|
heats="heats"
|
||||||
|
selected-heat="selectedHeat"
|
||||||
|
depth-range="depthRange"></hz-entities-toolbox>
|
||||||
<hz-entities-graph data="vm.graphData"
|
<hz-entities-graph data="vm.graphData"
|
||||||
selected="vm.model.selected"
|
selected="vm.model.selected"
|
||||||
search-item="searchText"
|
search-item="searchText"
|
||||||
@ -16,4 +20,4 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -23,7 +23,7 @@ function hzEntitiesGraph() {
|
|||||||
var minZoom = 0.3,
|
var minZoom = 0.3,
|
||||||
maxZoom = 4,
|
maxZoom = 4,
|
||||||
linkWidth = 1,
|
linkWidth = 1,
|
||||||
circleRadius = 14,
|
circleRadius = 18,
|
||||||
circlePadding = 1,
|
circlePadding = 1,
|
||||||
zoom = d3.behavior.zoom().scaleExtent([minZoom, maxZoom]),
|
zoom = d3.behavior.zoom().scaleExtent([minZoom, maxZoom]),
|
||||||
ellipsisWidth = 80,
|
ellipsisWidth = 80,
|
||||||
@ -361,7 +361,7 @@ function hzEntitiesGraph() {
|
|||||||
.attr('dominant-baseline', 'central')
|
.attr('dominant-baseline', 'central')
|
||||||
.attr('transform', 'scale(1)')
|
.attr('transform', 'scale(1)')
|
||||||
.attr('class', function(d) {
|
.attr('class', function(d) {
|
||||||
var category = d.category,
|
var category = d.vitrage_category,
|
||||||
cls = '';
|
cls = '';
|
||||||
|
|
||||||
if (category && category.toLowerCase() === 'alarm') {
|
if (category && category.toLowerCase() === 'alarm') {
|
||||||
@ -407,7 +407,7 @@ function hzEntitiesGraph() {
|
|||||||
return cls;
|
return cls;
|
||||||
})
|
})
|
||||||
.style('font-size', function(d) {
|
.style('font-size', function(d) {
|
||||||
var category = d.category || 'no_category',
|
var category = d.vitrage_category || 'no_category',
|
||||||
icon_size;
|
icon_size;
|
||||||
|
|
||||||
if (category && category.toLowerCase() === 'alarm') {
|
if (category && category.toLowerCase() === 'alarm') {
|
||||||
@ -437,11 +437,11 @@ function hzEntitiesGraph() {
|
|||||||
return icon_size;
|
return icon_size;
|
||||||
})
|
})
|
||||||
.style('stroke', function(d) {
|
.style('stroke', function(d) {
|
||||||
var category = d.category;
|
var category = d.vitrage_category;
|
||||||
if (category && category.toLowerCase() === 'alarm') {
|
if (category && category.toLowerCase() === 'alarm') {
|
||||||
return '18px'
|
return '18px';
|
||||||
}
|
}
|
||||||
return '20px'
|
return '20px';
|
||||||
})
|
})
|
||||||
.classed('icon', true)
|
.classed('icon', true)
|
||||||
.classed('fill-only', function(d) {
|
.classed('fill-only', function(d) {
|
||||||
@ -451,7 +451,7 @@ function hzEntitiesGraph() {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.text(function(d) {
|
.text(function(d) {
|
||||||
var category = d.category,
|
var category = d.vitrage_category,
|
||||||
icon;
|
icon;
|
||||||
|
|
||||||
if (category && category.toLowerCase() === 'alarm') {
|
if (category && category.toLowerCase() === 'alarm') {
|
||||||
@ -480,12 +480,15 @@ function hzEntitiesGraph() {
|
|||||||
case 'openstack.cluster':
|
case 'openstack.cluster':
|
||||||
icon = '\uf0c2'; //fa-cloud
|
icon = '\uf0c2'; //fa-cloud
|
||||||
break;
|
break;
|
||||||
|
case 'heat.stack':
|
||||||
|
icon = '\uf1b3'; //fa-cubes
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
icon = '\uf013'; //fa-cog
|
icon = '\uf013'; //fa-cog
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return icon
|
return icon;
|
||||||
});
|
});
|
||||||
|
|
||||||
content.append('text')
|
content.append('text')
|
||||||
@ -493,7 +496,7 @@ function hzEntitiesGraph() {
|
|||||||
.attr('dx', '-18px')
|
.attr('dx', '-18px')
|
||||||
.attr('dy', '-12px')
|
.attr('dy', '-12px')
|
||||||
.text('\uf08d')
|
.text('\uf08d')
|
||||||
.on('click', pinNode)
|
.on('click', pinNode);
|
||||||
|
|
||||||
var textNode = content.append('text')
|
var textNode = content.append('text')
|
||||||
.classed('.label', true)
|
.classed('.label', true)
|
||||||
@ -510,7 +513,7 @@ function hzEntitiesGraph() {
|
|||||||
}
|
}
|
||||||
d.width = 2 * (circleRadius + circlePadding) + (d.bbox ? d.bbox.width * 2 : 0);
|
d.width = 2 * (circleRadius + circlePadding) + (d.bbox ? d.bbox.width * 2 : 0);
|
||||||
d.height = 2 * (circleRadius + circlePadding);
|
d.height = 2 * (circleRadius + circlePadding);
|
||||||
})
|
});
|
||||||
})
|
})
|
||||||
.append('title')
|
.append('title')
|
||||||
.text(function(d) { return d.name; });
|
.text(function(d) { return d.name; });
|
||||||
@ -576,7 +579,7 @@ function hzEntitiesGraph() {
|
|||||||
|
|
||||||
svg_g.selectAll('.link').classed('selected', function(d) {
|
svg_g.selectAll('.link').classed('selected', function(d) {
|
||||||
return d.source.high && d.target.high;
|
return d.source.high && d.target.high;
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function selectNone(d) {
|
function selectNone(d) {
|
||||||
@ -697,7 +700,7 @@ function hzEntitiesGraph() {
|
|||||||
findNodes(node, depth, allNodes, linksMap);
|
findNodes(node, depth, allNodes, linksMap);
|
||||||
} else if (depth <= -1) {
|
} else if (depth <= -1) {
|
||||||
//Always find 'depth' + alarms & (sdns + alarms)
|
//Always find 'depth' + alarms & (sdns + alarms)
|
||||||
if (node.category.toLowerCase() === 'alarm') {
|
if (node && node.vitrage_category && node.vitrage_category.toLowerCase() === 'alarm') {
|
||||||
node.high = true;
|
node.high = true;
|
||||||
node.highDepth = 0;
|
node.highDepth = 0;
|
||||||
} else if (!node.high && node.vitrage_type && node.vitrage_type.toLowerCase() === 'sdn_controller') {
|
} else if (!node.high && node.vitrage_type && node.vitrage_type.toLowerCase() === 'sdn_controller') {
|
||||||
|
@ -16,5 +16,55 @@ function hzEntitiesInfo() {
|
|||||||
function link(scope, element, attrs) {
|
function link(scope, element, attrs) {
|
||||||
scope.blackList = ['name', 'vitrage_is_deleted', 'vitrage_is_placeholder', 'index', 'graph_index',
|
scope.blackList = ['name', 'vitrage_is_deleted', 'vitrage_is_placeholder', 'index', 'graph_index',
|
||||||
'fixed', 'weight', 'px', 'py', 'x', 'y', 'width', 'height', 'bbox', 'high', 'highDepth'];
|
'fixed', 'weight', 'px', 'py', 'x', 'y', 'width', 'height', 'bbox', 'high', 'highDepth'];
|
||||||
|
scope.parseItem = {};
|
||||||
|
|
||||||
|
// TODO: Order info by this priority
|
||||||
|
var topPriority = ['Vitrage resource type', 'Vitrage operational severity', 'Vitrage category', 'vitrage_aggregated_severity', 'vitrage_type', 'vitrage_operational_state']
|
||||||
|
|
||||||
|
scope.$watch('item', function (newData, oldData) {
|
||||||
|
if (newData !== undefined && newData != oldData) {
|
||||||
|
var tmpItem = copyObject(scope.item);
|
||||||
|
var itemParsed = {};
|
||||||
|
|
||||||
|
// 1. Replace _ with spaces
|
||||||
|
// 2. First letter uppercase
|
||||||
|
for (var property in tmpItem) {
|
||||||
|
if (scope.blackList.indexOf(property) < 0) {
|
||||||
|
if (tmpItem.hasOwnProperty(property)) {
|
||||||
|
var parsedProperty = '';
|
||||||
|
parsedProperty= property.split("_").join(" ");
|
||||||
|
parsedProperty = parsedProperty.charAt(0).toUpperCase() + parsedProperty.substr(1).toLowerCase();
|
||||||
|
itemParsed[parsedProperty] = tmpItem[property];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
scope.parseItem = itemParsed;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function copyObject(orig, deep) {
|
||||||
|
// 1. copy has same prototype as orig
|
||||||
|
var copy = Object.create(Object.getPrototypeOf(orig));
|
||||||
|
|
||||||
|
// 2. copy has all of orig’s properties
|
||||||
|
copyOwnPropertiesFrom(copy, orig, deep);
|
||||||
|
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
function copyOwnPropertiesFrom(target, source, deep) {
|
||||||
|
Object.getOwnPropertyNames(source)
|
||||||
|
.forEach(function(propKey) {
|
||||||
|
var desc = Object.getOwnPropertyDescriptor(source, propKey);
|
||||||
|
Object.defineProperty(target, propKey, desc);
|
||||||
|
if (deep && typeof desc.value === 'object') {
|
||||||
|
target[propKey] = copyObject(source[propKey], deep);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return target;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
<div class="entities-info" ng-show="item">
|
<div class="entities-info" ng-show="item">
|
||||||
<div class="info clearfix" ng-if="item.name">
|
<div class="info clearfix" ng-if="parseItem.name">
|
||||||
<span class="key pull-left ellipsis" title="{$ 'name' | translate $}">{$ 'name' | translate $}: </span>
|
<span class="key pull-left ellipsis font-title" title="{$ 'name' | translate $}">{$ 'name' | translate $}: </span>
|
||||||
<span class="value name pull-left ellipsis" title="{$ item.name $}"> {$ item.name $}</span>
|
<span class="value name pull-left ellipsis" title="{$ parseItem.name $}"> {$ parseItem.name $}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="info clearfix" ng-if="blackList.indexOf(key) < 0" ng-repeat="(key, value) in item">
|
<div class="info clearfix" ng-repeat="(key, value) in parseItem">
|
||||||
<span class="key pull-left ellipsis" title="{$ key | translate $}">{$ key | translate $}: </span>
|
<span class="key pull-left ellipsis keys-font font-title" title="{$ key | translate $}">{$ key | translate $}: </span>
|
||||||
<span class="value pull-left ellipsis" title="{$ value $}"> {$ value $}</span>
|
<span class="value pull-left ellipsis font-title" title="{$ value $}"> {$ value $}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
@ -2,13 +2,18 @@
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
margin: 12px;
|
margin: 12px;
|
||||||
padding:6px 10px;
|
padding:6px 10px;
|
||||||
width: 240px;
|
width: 446px;
|
||||||
min-height: 120px;
|
min-height: 120px;
|
||||||
max-height: 400px;
|
max-height: 400px;
|
||||||
border: 1px solid #ddd;
|
border: 1px solid #ddd;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background: rgba(255, 255, 255, 0.8);
|
background: rgba(255, 255, 255, 0.8);
|
||||||
|
opacity: 0.7;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
.info {
|
.info {
|
||||||
margin: 0 0 1px 0;
|
margin: 0 0 1px 0;
|
||||||
@ -27,4 +32,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.keys-font {
|
||||||
|
color: #428bca;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.font-title {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
}
|
}
|
@ -12,12 +12,17 @@ function hzEntitiesToolbox($rootScope) {
|
|||||||
scope: {
|
scope: {
|
||||||
item: '=',
|
item: '=',
|
||||||
searchText: '=',
|
searchText: '=',
|
||||||
autoRefresh: '='
|
autoRefresh: '=',
|
||||||
|
heats: '=',
|
||||||
|
selectedHeat: '=',
|
||||||
|
depthRange: '='
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return directive;
|
return directive;
|
||||||
|
|
||||||
function link(scope, element, attrs) {
|
function link(scope, element, attrs) {
|
||||||
|
scope.selectedHeat = 'all';
|
||||||
|
scope.depthRange = 2;
|
||||||
|
|
||||||
scope.autoRefresh = !!horizon.cookies.get('entitiesAutomaticRefresh');
|
scope.autoRefresh = !!horizon.cookies.get('entitiesAutomaticRefresh');
|
||||||
console.log('Getting autoRefresh cookie: ', scope.autoRefresh);
|
console.log('Getting autoRefresh cookie: ', scope.autoRefresh);
|
||||||
@ -25,6 +30,6 @@ function hzEntitiesToolbox($rootScope) {
|
|||||||
scope.broadcast = function(event) {
|
scope.broadcast = function(event) {
|
||||||
console.log('click', event);
|
console.log('click', event);
|
||||||
$rootScope.$broadcast('toolbox-' + event);
|
$rootScope.$broadcast('toolbox-' + event);
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,17 @@
|
|||||||
<div class="entities-toolbox">
|
<div class="entities-toolbox">
|
||||||
|
|
||||||
|
<div class="input-group input-group-xs heats-filter">
|
||||||
|
<select class="form-control" ng-model="selectedHeat">
|
||||||
|
<option value="all">All Heat Stacks</option>
|
||||||
|
<option ng-repeat="heat in heats track by $index" ng-value="heat.vitrageId">{{heat.name}}</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="input-group input-group-xs heats-filter" ng-show="selectedHeat !== 'all'">
|
||||||
|
<label translate>Detail Level</label>
|
||||||
|
<input type="range" min="1" max="4" ng-value="4" ng-model="depthRange" class="slider">
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="input-group input-group-xs">
|
<div class="input-group input-group-xs">
|
||||||
<span class="input-group-addon search-icon">
|
<span class="input-group-addon search-icon">
|
||||||
<span class="fa fa-search"></span>
|
<span class="fa fa-search"></span>
|
||||||
|
@ -33,4 +33,9 @@
|
|||||||
padding-left: 5px;
|
padding-left: 5px;
|
||||||
padding-top: 2px;
|
padding-top: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.heats-filter {
|
||||||
|
width: 100%;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,80 +1,81 @@
|
|||||||
(function() {
|
(function () {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
angular
|
angular
|
||||||
.module('horizon.dashboard.project.vitrage')
|
.module('horizon.dashboard.project.vitrage')
|
||||||
.service('vitrageTopologySrv', VitrageTopologySrv);
|
.service('vitrageTopologySrv', VitrageTopologySrv);
|
||||||
|
|
||||||
VitrageTopologySrv.$inject = ['$http', '$injector'];
|
VitrageTopologySrv.$inject = ['$http', '$injector'];
|
||||||
|
|
||||||
function VitrageTopologySrv($http, $injector) {
|
function VitrageTopologySrv($http, $injector) {
|
||||||
var vitrageAPI;
|
var vitrageAPI;
|
||||||
|
|
||||||
if ($injector.has('horizon.app.core.openstack-service-api.vitrage')) {
|
if ($injector.has('horizon.app.core.openstack-service-api.vitrage')) {
|
||||||
vitrageAPI = $injector.get('horizon.app.core.openstack-service-api.vitrage');
|
vitrageAPI = $injector.get('horizon.app.core.openstack-service-api.vitrage');
|
||||||
|
|
||||||
}
|
}
|
||||||
function getTopology(graph_type,config,admin) {
|
|
||||||
|
|
||||||
if (vitrageAPI) {
|
function getTopology(graph_type, config, admin) {
|
||||||
return vitrageAPI.getTopology(graph_type,config,admin)
|
|
||||||
.success(function(data) {
|
if (vitrageAPI) {
|
||||||
return data;
|
return vitrageAPI.getTopology(graph_type, config, admin)
|
||||||
})
|
.success(function (data) {
|
||||||
.error(function(err) {
|
return data;
|
||||||
console.error(err);
|
})
|
||||||
|
.error(function (err) {
|
||||||
|
console.error(err);
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
)
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getAlarms(vitrage_id,admin) {
|
function getAlarms(vitrage_id, admin) {
|
||||||
|
|
||||||
if (vitrageAPI) {
|
if (vitrageAPI) {
|
||||||
return vitrageAPI.getAlarms(vitrage_id,admin)
|
return vitrageAPI.getAlarms(vitrage_id, admin)
|
||||||
.success(function(data) {
|
.success(function (data) {
|
||||||
return data;
|
return data;
|
||||||
})
|
})
|
||||||
.error(function(err) {
|
.error(function (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
)
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getTemplates(template_id) {
|
function getTemplates(template_id) {
|
||||||
|
|
||||||
if (vitrageAPI) {
|
if (vitrageAPI) {
|
||||||
return vitrageAPI.getTemplates(template_id)
|
return vitrageAPI.getTemplates(template_id)
|
||||||
.success(function(data) {
|
.success(function (data) {
|
||||||
return data;
|
return data;
|
||||||
})
|
})
|
||||||
.error(function(err) {
|
.error(function (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
)
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function getRootCauseAnalysis(alarm_id,adminState) {
|
function getRootCauseAnalysis(alarm_id, adminState) {
|
||||||
if (vitrageAPI) {
|
if (vitrageAPI) {
|
||||||
return vitrageAPI.getRca(alarm_id,adminState)
|
return vitrageAPI.getRca(alarm_id, adminState)
|
||||||
.success(function(data) {
|
.success(function (data) {
|
||||||
return data;
|
return data;
|
||||||
})
|
})
|
||||||
.error(function(err) {
|
.error(function (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
)
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
getTopology: getTopology,
|
getTopology: getTopology,
|
||||||
getAlarms: getAlarms,
|
getAlarms: getAlarms,
|
||||||
getRootCauseAnalysis: getRootCauseAnalysis,
|
getRootCauseAnalysis: getRootCauseAnalysis,
|
||||||
getTemplates: getTemplates
|
getTemplates: getTemplates
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
|
||||||
})();
|
})();
|
||||||
|
Loading…
Reference in New Issue
Block a user