ceilometer has been removed from openstack-dashboard
openstack-dashboard team removed code related to ceilometer in its API part (https://review.openstack.org/#/c/399298/). So we can no more use it from our source code. I clean our code by removing tests about metering feature. Change-Id: I837d780454d44d1c4520a9d54bb04ccdc135f92b Closes-bug: #1649935
This commit is contained in:
parent
592b867492
commit
d9b9565918
@ -1,297 +0,0 @@
|
||||
# -*- coding: utf8 -*-
|
||||
#
|
||||
# Licensed 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.
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import copy
|
||||
|
||||
from django.utils.http import urlencode
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from horizon import exceptions
|
||||
from openstack_dashboard.api import ceilometer
|
||||
from openstack_dashboard.utils import metering
|
||||
|
||||
SETTINGS = {
|
||||
'settings': {
|
||||
'renderer': 'StaticAxes',
|
||||
'xMin': None,
|
||||
'xMax': None,
|
||||
'higlight_last_point': True,
|
||||
'auto_size': False,
|
||||
'auto_resize': False,
|
||||
'axes_x': False,
|
||||
'axes_y': True,
|
||||
'axes_y_label': False,
|
||||
'bar_chart_settings': {
|
||||
'orientation': 'vertical',
|
||||
'used_label_placement': 'left',
|
||||
'width': 30,
|
||||
'color_scale_domain': [0, 80, 80, 100],
|
||||
'color_scale_range': [
|
||||
'#0000FF',
|
||||
'#0000FF',
|
||||
'#FF0000',
|
||||
'#FF0000'
|
||||
],
|
||||
'average_color_scale_domain': [0, 100],
|
||||
'average_color_scale_range': ['#0000FF', '#0000FF']
|
||||
}
|
||||
},
|
||||
'stats': {
|
||||
'average': None,
|
||||
'used': None,
|
||||
'tooltip_average': None,
|
||||
}
|
||||
}
|
||||
|
||||
LABELS = {
|
||||
'hardware.cpu.load.1min': _("CPU load 1 min average"),
|
||||
'hardware.system_stats.cpu.util': _("CPU utilization"),
|
||||
'hardware.system_stats.io.outgoing.blocks': _("IO raw sent"),
|
||||
'hardware.system_stats.io.incoming.blocks': _("IO raw received"),
|
||||
'hardware.network.ip.outgoing.datagrams': _("IP out requests"),
|
||||
'hardware.network.ip.incoming.datagrams': _("IP in requests"),
|
||||
'hardware.memory.swap.util': _("Swap utilization"),
|
||||
'hardware.ipmi.fan': _("Fan Speed"),
|
||||
'hardware.ipmi.voltage': _("Votage"),
|
||||
'hardware.ipmi.temperature': _("Temperature"),
|
||||
'hardware.ipmi.current': _("Current")
|
||||
}
|
||||
|
||||
|
||||
# TODO(lsmola) this should probably live in Horizon common
|
||||
def query_data(request,
|
||||
date_from,
|
||||
date_to,
|
||||
group_by,
|
||||
meter,
|
||||
period=None,
|
||||
query=None,
|
||||
additional_query=None):
|
||||
|
||||
if not period:
|
||||
period = metering.calc_period(date_from, date_to, 50)
|
||||
if additional_query is None:
|
||||
additional_query = []
|
||||
if date_from:
|
||||
additional_query += [{'field': 'timestamp',
|
||||
'op': 'ge',
|
||||
'value': date_from}]
|
||||
if date_to:
|
||||
additional_query += [{'field': 'timestamp',
|
||||
'op': 'le',
|
||||
'value': date_to}]
|
||||
|
||||
# TODO(lsmola) replace this by logic implemented in I1 in bugs
|
||||
# 1226479 and 1226482, this is just a quick fix for RC1
|
||||
ceilometer_usage = ceilometer.CeilometerUsage(request)
|
||||
try:
|
||||
if group_by:
|
||||
resources = ceilometer_usage.resource_aggregates_with_statistics(
|
||||
query, [meter], period=period, stats_attr=None,
|
||||
additional_query=additional_query)
|
||||
else:
|
||||
resources = ceilometer_usage.resources_with_statistics(
|
||||
query, [meter], period=period, stats_attr=None,
|
||||
additional_query=additional_query)
|
||||
except Exception:
|
||||
resources = []
|
||||
exceptions.handle(request,
|
||||
_('Unable to retrieve statistics.'))
|
||||
return resources
|
||||
|
||||
|
||||
def url_part(meter_name, barchart):
|
||||
d = {'meter': meter_name}
|
||||
if barchart:
|
||||
d['barchart'] = True
|
||||
return urlencode(d)
|
||||
|
||||
|
||||
def get_meter_name(meter):
|
||||
return meter.replace('.', '_')
|
||||
|
||||
|
||||
def get_meter_list_and_unit(request, meter):
|
||||
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 = ''
|
||||
|
||||
return meter_list, unit
|
||||
|
||||
|
||||
def get_meters(meters):
|
||||
return [(m, get_meter_name(m)) for m in meters]
|
||||
|
||||
|
||||
def get_barchart_stats(series, unit):
|
||||
values = [point['y'] for point in series[0]['data']]
|
||||
average = sum(values) / float(len(values)) # Python 2/3 compatibility
|
||||
used = values[-1]
|
||||
first_date = series[0]['data'][0]['x']
|
||||
last_date = series[0]['data'][-1]['x']
|
||||
tooltip_average = _('Average %(average)s %(unit)s<br> From: '
|
||||
'%(first_date)s, to: %(last_date)s') % (
|
||||
dict(average=average, unit=unit,
|
||||
first_date=first_date,
|
||||
last_date=last_date))
|
||||
return average, used, tooltip_average
|
||||
|
||||
|
||||
def create_json_output(series, barchart, unit, date_from, date_to):
|
||||
start_datetime = end_datetime = ''
|
||||
if date_from:
|
||||
start_datetime = date_from.strftime("%Y-%m-%dT%H:%M:%S")
|
||||
if date_to:
|
||||
end_datetime = date_to.strftime("%Y-%m-%dT%H:%M:%S")
|
||||
|
||||
settings = copy.deepcopy(SETTINGS)
|
||||
settings['settings']['xMin'] = start_datetime
|
||||
settings['settings']['xMax'] = end_datetime
|
||||
|
||||
if series and barchart:
|
||||
average, used, tooltip_average = get_barchart_stats(series, unit)
|
||||
settings['settings']['yMin'] = 0
|
||||
settings['settings']['yMax'] = 100
|
||||
settings['stats']['average'] = average
|
||||
settings['stats']['used'] = used
|
||||
settings['stats']['tooltip_average'] = tooltip_average
|
||||
else:
|
||||
del settings['settings']['bar_chart_settings']
|
||||
del settings['stats']
|
||||
|
||||
json_output = {'series': series}
|
||||
json_output.update(settings)
|
||||
return json_output
|
||||
|
||||
|
||||
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 = []
|
||||
meter_list, unit = get_meter_list_and_unit(request, meter)
|
||||
|
||||
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:
|
||||
# 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':
|
||||
meters = get_meters([
|
||||
'hardware.system_stats.io.outgoing.blocks',
|
||||
'hardware.system_stats.io.incoming.blocks'
|
||||
])
|
||||
elif meter == 'network-io':
|
||||
meters = get_meters([
|
||||
'hardware.network.ip.outgoing.datagrams',
|
||||
'hardware.network.ip.incoming.datagrams'
|
||||
])
|
||||
else:
|
||||
meters = get_meters([meter])
|
||||
|
||||
date_from, date_to = metering.calc_date_args(
|
||||
date_from,
|
||||
date_to,
|
||||
date_options)
|
||||
|
||||
for meter_id, meter_name in meters:
|
||||
label = str(LABELS.get(meter_id, meter_name))
|
||||
|
||||
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)
|
||||
|
||||
json_output = create_json_output(
|
||||
series,
|
||||
barchart,
|
||||
unit,
|
||||
date_from,
|
||||
date_to)
|
||||
|
||||
return json_output
|
||||
|
||||
|
||||
def get_top_5(request, meter):
|
||||
ceilometer_usage = ceilometer.CeilometerUsage(request)
|
||||
meter_list, unit = get_meter_list_and_unit(request, meter)
|
||||
top_5 = {'unit': unit, 'label': LABELS.get(meter, meter)}
|
||||
data = []
|
||||
|
||||
for m in meter_list:
|
||||
query = [{'field': 'resource_id', 'op': 'eq', 'value': m.resource_id}]
|
||||
resource = ceilometer_usage.resources_with_statistics(query, [m.name],
|
||||
period=600)[0]
|
||||
node_uuid = resource.metadata['node']
|
||||
old_value, value = resource.get_meter(get_meter_name(m.name))[-2:]
|
||||
old_value, value = old_value.max, value.max
|
||||
|
||||
if value > old_value:
|
||||
direction = 'up'
|
||||
elif value < old_value:
|
||||
direction = 'down'
|
||||
else:
|
||||
direction = None
|
||||
|
||||
data.append({
|
||||
'node_uuid': node_uuid,
|
||||
'value': value,
|
||||
'direction': direction
|
||||
})
|
||||
|
||||
top_5['data'] = sorted(data, key=lambda d: d['value'], reverse=True)[:5]
|
||||
return top_5
|
@ -13,13 +13,8 @@
|
||||
# under the License.
|
||||
|
||||
import collections
|
||||
import datetime
|
||||
|
||||
import mock
|
||||
|
||||
from watcher_dashboard.test import helpers
|
||||
|
||||
from watcher_dashboard.utils import metering
|
||||
from watcher_dashboard.utils import utils
|
||||
|
||||
|
||||
@ -77,132 +72,3 @@ class UtilsTests(helpers.TestCase):
|
||||
self.assertEqual(ret, 0)
|
||||
ret = utils.safe_int_cast(object())
|
||||
self.assertEqual(ret, 0)
|
||||
|
||||
|
||||
class MeteringTests(helpers.TestCase):
|
||||
def test_query_data(self):
|
||||
Meter = collections.namedtuple('Meter', 'name unit')
|
||||
request = 'request'
|
||||
from_date = datetime.datetime(2015, 1, 1, 13, 45)
|
||||
to_date = datetime.datetime(2015, 1, 2, 13, 45)
|
||||
with mock.patch(
|
||||
'openstack_dashboard.api.ceilometer.meter_list',
|
||||
return_value=[Meter('foo.bar', u'µD')],
|
||||
), mock.patch(
|
||||
'openstack_dashboard.api.ceilometer.CeilometerUsage',
|
||||
return_value=mock.MagicMock(**{
|
||||
'resource_aggregates_with_statistics.return_value': 'plonk',
|
||||
}),
|
||||
):
|
||||
ret = metering.query_data(request, from_date, to_date,
|
||||
'all', 'foo.bar')
|
||||
self.assertEqual(ret, 'plonk')
|
||||
|
||||
def test_url_part(self):
|
||||
ret = metering.url_part('foo_bar_baz', True)
|
||||
self.assertTrue('meter=foo_bar_baz' in ret)
|
||||
self.assertTrue('barchart=True' in ret)
|
||||
ret = metering.url_part('foo_bar_baz', False)
|
||||
self.assertTrue('meter=foo_bar_baz' in ret)
|
||||
self.assertFalse('barchart=True' in ret)
|
||||
|
||||
def test_get_meter_name(self):
|
||||
ret = metering.get_meter_name('foo.bar.baz')
|
||||
self.assertEqual(ret, 'foo_bar_baz')
|
||||
|
||||
def test_get_meters(self):
|
||||
ret = metering.get_meters(['foo.bar', 'foo.baz'])
|
||||
self.assertEqual(ret, [('foo.bar', 'foo_bar'), ('foo.baz', 'foo_baz')])
|
||||
|
||||
def test_get_barchart_stats(self):
|
||||
series = [
|
||||
{'data': [{'x': 1, 'y': 1}, {'x': 4, 'y': 4}]},
|
||||
{'data': [{'x': 2, 'y': 2}, {'x': 5, 'y': 5}]},
|
||||
{'data': [{'x': 3, 'y': 3}, {'x': 6, 'y': 6}]},
|
||||
]
|
||||
# Arrogance is measured in IT in micro-Dijkstras, µD.
|
||||
average, used, tooltip_average = metering.get_barchart_stats(series,
|
||||
u'µD')
|
||||
self.assertEqual(average, 2.5)
|
||||
self.assertEqual(used, 4)
|
||||
self.assertEqual(tooltip_average, u'Average 2.5 µD<br> From: 1, to: 4')
|
||||
|
||||
def test_create_json_output(self):
|
||||
ret = metering.create_json_output([], False, u'µD', None, None)
|
||||
self.assertEqual(ret, {
|
||||
'series': [],
|
||||
'settings': {
|
||||
'higlight_last_point': True,
|
||||
'axes_x': False,
|
||||
'axes_y': True,
|
||||
'xMin': '',
|
||||
'renderer': 'StaticAxes',
|
||||
'xMax': '',
|
||||
'axes_y_label': False,
|
||||
'auto_size': False,
|
||||
'auto_resize': False,
|
||||
},
|
||||
})
|
||||
|
||||
series = [
|
||||
{'data': [{'x': 1, 'y': 1}, {'x': 4, 'y': 4}]},
|
||||
{'data': [{'x': 2, 'y': 2}, {'x': 5, 'y': 5}]},
|
||||
{'data': [{'x': 3, 'y': 3}, {'x': 6, 'y': 6}]},
|
||||
]
|
||||
ret = metering.create_json_output(series, True, u'µD', None, None)
|
||||
self.assertEqual(ret, {
|
||||
'series': series,
|
||||
'stats': {
|
||||
'average': 2.5,
|
||||
'used': 4,
|
||||
'tooltip_average': u'Average 2.5 µD<br> From: 1, to: 4',
|
||||
},
|
||||
'settings': {
|
||||
'yMin': 0,
|
||||
'yMax': 100,
|
||||
'higlight_last_point': True,
|
||||
'axes_x': False,
|
||||
'axes_y': True,
|
||||
'bar_chart_settings': {
|
||||
'color_scale_domain': [0, 80, 80, 100],
|
||||
'orientation': 'vertical',
|
||||
'color_scale_range': [
|
||||
'#0000FF',
|
||||
'#0000FF',
|
||||
'#FF0000',
|
||||
'#FF0000',
|
||||
],
|
||||
'width': 30,
|
||||
'average_color_scale_domain': [0, 100],
|
||||
'used_label_placement': 'left',
|
||||
'average_color_scale_range': ['#0000FF', '#0000FF'],
|
||||
},
|
||||
'xMin': '',
|
||||
'renderer': 'StaticAxes',
|
||||
'xMax': '',
|
||||
'axes_y_label': False,
|
||||
'auto_size': False,
|
||||
'auto_resize': False,
|
||||
},
|
||||
})
|
||||
|
||||
def test_get_nodes_stats(self):
|
||||
request = 'request'
|
||||
with mock.patch(
|
||||
'watcher_dashboard.utils.metering.create_json_output',
|
||||
return_value='',
|
||||
) as create_json_output, mock.patch(
|
||||
'watcher_dashboard.utils.metering.query_data',
|
||||
return_value=[],
|
||||
), mock.patch(
|
||||
'openstack_dashboard.utils.metering.series_for_meter',
|
||||
return_value=[],
|
||||
), mock.patch(
|
||||
'openstack_dashboard.utils.metering.calc_date_args',
|
||||
return_value=('from date', 'to date'),
|
||||
):
|
||||
ret = metering.get_nodes_stats(request, 'abc', 'def', 'foo.bar')
|
||||
self.assertEqual(ret, '')
|
||||
self.assertEqual(create_json_output.call_args_list, [
|
||||
mock.call([], None, '', 'from date', 'to date')
|
||||
])
|
||||
|
Loading…
Reference in New Issue
Block a user