Add aggregated stat to nodes index

Adding aggregated stats to node index page.

Change-Id: I5c2c523037e7310c646ff05de71c0a6c11bf3419
This commit is contained in:
Ladislav Smola 2014-09-11 11:33:29 +02:00 committed by Radomir Dopieralski
parent e88f8a5bee
commit f05453020a
5 changed files with 140 additions and 12 deletions

View File

@ -50,7 +50,7 @@ class OverviewTab(tabs.Tab):
total_nodes_healthy = api.node.filter_nodes(total_nodes, healthy=True)
total_nodes_up = api.node.filter_nodes(total_nodes, power_state=True)
return {
context = {
'cpus': cpus,
'memory_gb': memory_mb / 1024.0,
'local_gb': local_gb,
@ -66,6 +66,23 @@ class OverviewTab(tabs.Tab):
'free_nodes_down': free_nodes_down,
}
if api_base.is_service_enabled(self.request, 'metering'):
context['meter_conf'] = (
(_('System Load'),
metering_utils.url_part('hardware.cpu.load.1min', False),
None),
(_('CPU Utilization'),
metering_utils.url_part('hardware.system_stats.cpu.util',
True),
'100'),
(_('Swap Utilization'),
metering_utils.url_part('hardware.memory.swap.util',
True),
'100'),
)
return context
class RegisteredTab(tabs.TableTab):
table_classes = (tables.RegisteredNodesTable,)

View File

@ -46,3 +46,104 @@
</div>
</div>
</div>
<div class="row">
<div class="col-xs-12">
<h3>{% trans "Provisioned nodes" %}</h3>
{% if meter_conf %}
{% url 'horizon:infrastructure:nodes:nodes_performance' as node_perf_url %}
<div id="ceilometer-stats" class="clearfix">
<form class="form-horizontal" id="linechart_general_form">
<div class="form-group">
<label for="date_options" class="control-label col-sm-3">{% trans "Period" %}:&nbsp;</label>
<div class="col-sm-4">
<select data-line-chart-command="select_box_change"
id="date_options"
name="date_options"
class="form-control">
<option value="0.041666">{% trans "Last hour" %}</option>
<option value="0.25">{% trans "Last 6 hours" %}</option>
<option value="0.5">{% trans "Last 12 hours" %}</option>
<option value="1" selected="selected">{% trans "Last day" %}</option>
<option value="7">{% trans "Last week" %}</option>
<option value="{% now 'j' %}">{% trans "Month to date" %}</option>
<option value="15">{% trans "Last 15 days" %}</option>
<option value="30">{% trans "Last 30 days" %}</option>
<option value="365">{% trans "Last year" %}</option>
<option value="other">{% trans "Other" %}</option>
</select>
</div>
</div>
<div class="form-group" id="date_from_group">
<label for="date_from" class="control-label col-sm-3">{% trans "From" %}:&nbsp;</label>
<div class="col-sm-4">
<input data-line-chart-command="date_picker_change"
type="text"
id="date_from"
name="date_from"
class="form-control"/>
</div>
</div>
<div class="form-group" id="date_to_group">
<label for="date_to" class="control-label col-sm-3">{% trans "To" %}:&nbsp;</label>
<div class="col-sm-4">
<input data-line-chart-command="date_picker_change"
type="text"
id="date_to"
name="date_to"
class="form-control"/>
</div>
</div>
</form>
</div>
<script type="text/javascript">
if (typeof $ !== 'undefined') {
show_hide_datepickers();
} else {
addHorizonLoadEvent(function() {
show_hide_datepickers();
});
}
// TODO(lsmola) Pull the common code into a js file.
function show_hide_datepickers() {
var date_options = $("#date_options");
date_options.change(function(evt) {
if ($(this).find("option:selected").val() === "other"){
evt.stopPropagation();
$("#date_from, #date_to").val('');
$("#date_from_group, #date_to_group").show();
} else {
$("#date_from_group, #date_to_group").hide();
}
});
if (date_options.find("option:selected").val() === "other"){
$("#date_from_group, #date_to_group").show();
} else {
$("#date_from_group, #date_to_group").hide();
}
}
</script>
<div id="node-charts" class="nodes row">
<div class="col-lg-1">
<div class="widget-info">
<a href="{% url 'horizon:infrastructure:nodes:index' %}?tab=nodes__registered">
<span class="info">{{ deployed_nodes|length|default:0 }}</span><br>
{% trans 'Provisioned' %}<br>
{% trans 'Nodes' %}<br>
</a>
</div>
</div>
{% for meter_label, url_part, y_max in meter_conf %}
<div class="col-lg-3">
{% include "infrastructure/_performance_chart.html" with label=meter_label y_max=y_max url=node_perf_url|add:"?"|add:url_part only %}
</div>
{% endfor %}
{% else %}
<p>{% trans 'Metering service is not enabled.' %}</p>
{% endif %}
</div>
</div>
</div>

View File

@ -24,6 +24,8 @@ urlpatterns = urls.patterns(
name='register'),
urls.url(r'^auto-discover/$', views.AutoDiscoverView.as_view(),
name='auto-discover'),
urls.url(r'^nodes_performance/$',
views.PerformanceView.as_view(), name='nodes_performance'),
urls.url(r'^(?P<node_uuid>[^/]+)/$', views.DetailView.as_view(),
name='detail'),
urls.url(r'^(?P<node_uuid>[^/]+)/performance/$',

View File

@ -108,18 +108,21 @@ class PerformanceView(base.TemplateView):
stats_attr = request.GET.get('stats_attr', 'avg')
barchart = bool(request.GET.get('barchart'))
node_uuid = kwargs.get('node_uuid')
node = api.node.Node.get(request, node_uuid)
try:
instance_uuid = node.instance_uuid
except AttributeError:
json_output = None
node_uuid = kwargs.get('node_uuid', None)
if node_uuid:
node = api.node.Node.get(request, node_uuid)
try:
instance_uuid = node.instance_uuid
except AttributeError:
json_output = None
else:
json_output = metering_utils.get_nodes_stats(
request, instance_uuid, meter, date_options=date_options,
date_from=date_from, date_to=date_to, stats_attr=stats_attr,
barchart=barchart)
# Aggregated stats for all nodes
instance_uuid = None
json_output = metering_utils.get_nodes_stats(
request, instance_uuid, meter, date_options=date_options,
date_from=date_from, date_to=date_to,
stats_attr=stats_attr, barchart=barchart)
return http.HttpResponse(json.dumps(json_output),
content_type='application/json')

View File

@ -270,6 +270,11 @@ def get_nodes_stats(request, uuid, meter, date_options=None, date_from=None,
query = [{'field': 'resource_id',
'op': 'eq',
'value': uuid}]
else:
# query will be aggregated across all resources
group_by = "all"
query = {}
query['all'] = []
# Disk and Network I/O: data from 2 meters in one chart
if meter == 'disk-io':