Add IPMI metrics to node detail page

Add four new IPMI metrics (Current, Temperature, Fan Speed and
Voltage) to the node detail page.

Change-Id: I0ea141f146c5d946919af2a70cff51bf2a8dec67
This commit is contained in:
Ana Krivokapic 2015-02-27 12:31:11 +01:00
parent ef98fbb619
commit 10ec89b16e
5 changed files with 77 additions and 44 deletions

View File

@ -306,10 +306,11 @@ class DetailOverviewTab(tabs.Tab):
else:
context['role'] = resource.role
context['stack'] = resource.stack
if node.instance_uuid:
if api_base.is_service_enabled(self.request, 'metering'):
# Meter configuration in the following format:
# (meter label, url part, barchart (True/False))
# (meter label, url part, y_max)
context['meter_conf'] = (
(_('System Load'),
metering_utils.url_part('hardware.cpu.load.1min', False),
@ -322,11 +323,24 @@ class DetailOverviewTab(tabs.Tab):
metering_utils.url_part('hardware.memory.swap.util',
True),
'100'),
(_('Disk I/O '),
(_('Current'),
metering_utils.url_part('hardware.ipmi.current', False),
None),
(_('Network IO'),
metering_utils.url_part('network-io', False),
None),
(_('Disk IO'),
metering_utils.url_part('disk-io', False),
None),
(_('Network I/O '),
metering_utils.url_part('network-io', False),
(_('Temperature'),
metering_utils.url_part('hardware.ipmi.temperature',
False),
None),
(_('Fan Speed'),
metering_utils.url_part('hardware.ipmi.fan', False),
None),
(_('Voltage'),
metering_utils.url_part('hardware.ipmi.voltage', False),
None),
)
return context

View File

@ -404,7 +404,7 @@ class NodesTests(test.BaseAdminViewTests):
'server_list.return_value': ([instance], None),
}),
patch('tuskar_ui.utils.metering.query_data',
return_value=([], 'unit')),
return_value=[]),
):
url = urlresolvers.reverse(PERFORMANCE_VIEW, args=(node.uuid,))
url += '?meter=cpu&date_options=7'

View File

@ -156,8 +156,8 @@ class PerformanceView(base.TemplateView):
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,
request, node_uuid, instance_uuid, meter,
date_options=date_options, date_from=date_from, date_to=date_to,
stats_attr=stats_attr, barchart=barchart)
return django.http.HttpResponse(

View File

@ -88,13 +88,6 @@ def query_data(request,
# TODO(lsmola) replace this by logic implemented in I1 in bugs
# 1226479 and 1226482, this is just a quick fix for RC1
try:
meter_list = [m for m in ceilometer.meter_list(request)
if m.name == meter]
unit = meter_list[0].unit
except Exception:
unit = ""
ceilometer_usage = ceilometer.CeilometerUsage(request)
try:
if group_by:
@ -109,7 +102,7 @@ def query_data(request,
resources = []
exceptions.handle(request,
_('Unable to retrieve statistics.'))
return resources, unit
return resources
def url_part(meter_name, barchart):
@ -168,28 +161,51 @@ def create_json_output(series, barchart, unit, date_from, date_to):
return json_output
def get_nodes_stats(request, uuid, meter, date_options=None, date_from=None,
date_to=None, stats_attr=None, barchart=None,
group_by=None):
unit = ''
def get_nodes_stats(request, node_uuid, instance_uuid, meter,
date_options=None, date_from=None, date_to=None,
stats_attr=None, barchart=None, group_by=None):
series = []
if uuid:
if group_by == "image_id":
query = {}
image_query = [{"field": "metadata.%s" % group_by,
"op": "eq",
"value": uuid}]
query[uuid] = image_query
try:
meter_list = [m for m in ceilometer.meter_list(request)
if m.name == meter]
unit = meter_list[0].unit
except Exception:
meter_list = []
unit = ''
if instance_uuid:
if 'ipmi' in meter:
# For IPMI metrics, a resource ID is made of node UUID concatenated
# with the metric description. E.g:
# 1dcf1896-f581-4027-9efa-973eef3380d2-fan_2a_tach_(0x42)
resource_ids = [m.resource_id for m in meter_list
if m.resource_id.startswith(node_uuid)]
queries = [
[{'field': 'resource_id',
'op': 'eq',
'value': resource_id}]
for resource_id in resource_ids
]
else:
query = [{'field': 'resource_id',
'op': 'eq',
'value': uuid}]
# For SNMP metrics, a resource ID matches exactly the UUID of the
# associated instance
if group_by == "image_id":
query = {}
image_query = [{"field": "metadata.%s" % group_by,
"op": "eq",
"value": instance_uuid}]
query[instance_uuid] = image_query
else:
query = [{'field': 'resource_id',
'op': 'eq',
'value': instance_uuid}]
queries = [query]
else:
# query will be aggregated across all resources
group_by = "all"
query = {'all': []}
queries = [query]
# Disk and Network I/O: data from 2 meters in one chart
if meter == 'disk-io':
@ -212,16 +228,19 @@ def get_nodes_stats(request, uuid, meter, date_options=None, date_from=None,
for meter_id, meter_name in meters:
label = unicode(LABELS.get(meter_id, meter_name))
resources, unit = query_data(
request=request,
date_from=date_from,
date_to=date_to,
group_by=group_by,
meter=meter_id,
query=query)
s = metering.series_for_meter(request, resources, group_by, meter_id,
meter_name, stats_attr, unit, label)
series += s
for query in queries:
resources = query_data(
request=request,
date_from=date_from,
date_to=date_to,
group_by=group_by,
meter=meter_id,
query=query)
s = metering.series_for_meter(request, resources, group_by,
meter_id, meter_name, stats_attr,
unit, label)
series += s
series = metering.normalize_series_by_unit(series)

View File

@ -95,7 +95,7 @@ class MeteringTests(helpers.TestCase):
):
ret = metering.query_data(request, from_date, to_date,
'all', 'foo.bar')
self.assertEqual(ret, ('plonk', u'µD'))
self.assertEqual(ret, 'plonk')
def test_url_part(self):
ret = metering.url_part('foo_bar_baz', True)
@ -192,7 +192,7 @@ class MeteringTests(helpers.TestCase):
return_value='',
) as create_json_output, mock.patch(
'tuskar_ui.utils.metering.query_data',
return_value=([], u'µD'),
return_value=[],
), mock.patch(
'openstack_dashboard.utils.metering.series_for_meter',
return_value=[],
@ -200,8 +200,8 @@ class MeteringTests(helpers.TestCase):
'openstack_dashboard.utils.metering.calc_date_args',
return_value=('from date', 'to date'),
):
ret = metering.get_nodes_stats(request, 'abc', 'foo.bar')
ret = metering.get_nodes_stats(request, 'abc', 'def', 'foo.bar')
self.assertEqual(ret, '')
self.assertEqual(create_json_output.call_args_list, [
mock.call([], None, u'µD', 'from date', 'to date')
mock.call([], None, '', 'from date', 'to date')
])