Extracting common function into utils
Extracting common metering functins into utils/metering so they can be reused in multiple places. Moving old utils file under utils directory. Change-Id: Id45b6237a68a894721e1b2051f64192781f02f8f
This commit is contained in:
parent
8eaaf5529b
commit
7ed35dee84
@ -28,7 +28,7 @@ from tuskar_ui.api import tuskar
|
||||
from tuskar_ui.cached_property import cached_property # noqa
|
||||
from tuskar_ui.handle_errors import handle_errors # noqa
|
||||
from tuskar_ui.test.test_data import heat_data
|
||||
from tuskar_ui import utils
|
||||
from tuskar_ui.utils import utils
|
||||
|
||||
|
||||
TEST_DATA = test_utils.TestDataContainer()
|
||||
|
@ -24,7 +24,7 @@ from tuskar_ui.cached_property import cached_property # noqa
|
||||
from tuskar_ui.handle_errors import handle_errors # noqa
|
||||
from tuskar_ui.test.test_data import heat_data
|
||||
from tuskar_ui.test.test_data import node_data
|
||||
from tuskar_ui import utils
|
||||
from tuskar_ui.utils import utils
|
||||
|
||||
|
||||
TEST_DATA = test_utils.TestDataContainer()
|
||||
|
@ -11,16 +11,10 @@
|
||||
# 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 datetime import datetime # noqa
|
||||
from datetime import timedelta # noqa
|
||||
from django.utils import timezone
|
||||
|
||||
import json
|
||||
|
||||
from django.core.urlresolvers import reverse_lazy
|
||||
from django import http
|
||||
from django.utils.http import urlencode
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.views.generic import base
|
||||
|
||||
@ -30,13 +24,11 @@ from horizon import tabs as horizon_tabs
|
||||
from horizon import views as horizon_views
|
||||
|
||||
from openstack_dashboard.api import base as api_base
|
||||
from openstack_dashboard.api import ceilometer
|
||||
|
||||
from openstack_dashboard.dashboards.admin.metering import views as metering
|
||||
|
||||
from tuskar_ui import api
|
||||
from tuskar_ui.infrastructure.nodes import forms
|
||||
from tuskar_ui.infrastructure.nodes import tabs
|
||||
from tuskar_ui.utils import metering as metering_utils
|
||||
|
||||
|
||||
class IndexView(horizon_tabs.TabbedTableView):
|
||||
@ -81,19 +73,20 @@ class DetailView(horizon_views.APIView):
|
||||
# (meter label, url part, barchart (True/False))
|
||||
context['meter_conf'] = (
|
||||
(_('System Load'),
|
||||
url_part('hardware.cpu.load.1min', False),
|
||||
metering_utils.url_part('hardware.cpu.load.1min', False),
|
||||
None),
|
||||
(_('CPU Utilization'),
|
||||
url_part('hardware.system_stats.cpu.util', True),
|
||||
metering_utils.url_part('hardware.system_stats.cpu.util',
|
||||
True),
|
||||
'100'),
|
||||
(_('Swap Utilization'),
|
||||
url_part('swap-util', True),
|
||||
metering_utils.url_part('swap-util', True),
|
||||
'100'),
|
||||
(_('Disk I/O '),
|
||||
url_part('disk-io', False),
|
||||
metering_utils.url_part('disk-io', False),
|
||||
None),
|
||||
(_('Network I/O '),
|
||||
url_part('network-io', False),
|
||||
metering_utils.url_part('network-io', False),
|
||||
None),
|
||||
)
|
||||
return context
|
||||
@ -161,29 +154,30 @@ class PerformanceView(base.TemplateView):
|
||||
|
||||
# Disk and Network I/O: data from 2 meters in one chart
|
||||
if meter == 'disk-io':
|
||||
meters = get_meters([
|
||||
meters = metering_utils.get_meters([
|
||||
'hardware.system_stats.io.raw_sent',
|
||||
'hardware.system_stats.io.raw_received'
|
||||
])
|
||||
elif meter == 'network-io':
|
||||
meters = get_meters([
|
||||
meters = metering_utils.get_meters([
|
||||
'hardware.network.ip.out_requests',
|
||||
'hardware.network.ip.in_receives'
|
||||
])
|
||||
elif meter == 'swap-util':
|
||||
meters = get_meters([
|
||||
meters = metering_utils.get_meters([
|
||||
'hardware.memory.swap.util',
|
||||
'hardware.memory.swap.total'
|
||||
])
|
||||
else:
|
||||
meters = get_meters([meter])
|
||||
meters = metering_utils.get_meters([meter])
|
||||
|
||||
date_from, date_to = _calc_date_args(date_from,
|
||||
date_to,
|
||||
date_options)
|
||||
date_from, date_to = metering_utils._calc_date_args(
|
||||
date_from,
|
||||
date_to,
|
||||
date_options)
|
||||
|
||||
for meter_id, meter_name in meters:
|
||||
resources, unit = query_data(
|
||||
resources, unit = metering_utils.query_data(
|
||||
request=request,
|
||||
date_from=date_from,
|
||||
date_to=date_to,
|
||||
@ -219,193 +213,25 @@ class PerformanceView(base.TemplateView):
|
||||
series = [util]
|
||||
|
||||
if series and barchart:
|
||||
average, used, tooltip_average = get_barchart_stats(series,
|
||||
unit)
|
||||
average, used, tooltip_average = (
|
||||
metering_utils.get_barchart_stats(series, unit))
|
||||
|
||||
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")
|
||||
|
||||
json_output = create_json_output(series, start_datetime, end_datetime)
|
||||
json_output = metering_utils.create_json_output(
|
||||
series,
|
||||
start_datetime,
|
||||
end_datetime)
|
||||
|
||||
if series and barchart:
|
||||
json_output = add_barchart_settings(json_output, average, used,
|
||||
tooltip_average)
|
||||
json_output = metering_utils.add_barchart_settings(
|
||||
json_output,
|
||||
average,
|
||||
used,
|
||||
tooltip_average)
|
||||
|
||||
return http.HttpResponse(json.dumps(json_output),
|
||||
mimetype='application/json')
|
||||
|
||||
|
||||
#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 = _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
|
||||
try:
|
||||
meter_list = [m for m in metering.meter_list(request)
|
||||
if m.name == meter]
|
||||
unit = meter_list[0].unit
|
||||
except Exception:
|
||||
unit = ""
|
||||
if group_by == "resources":
|
||||
# TODO(lsmola) need to implement group_by groups of resources
|
||||
resources = []
|
||||
unit = ""
|
||||
else:
|
||||
ceilometer_usage = ceilometer.CeilometerUsage(request)
|
||||
try:
|
||||
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, unit
|
||||
|
||||
|
||||
#TODO(lsmola) push this function to Horizon common then delete this
|
||||
def _calc_period(date_from, date_to, number_of_samples=400):
|
||||
if date_from and date_to:
|
||||
if date_to < date_from:
|
||||
# TODO(lsmola) propagate the Value error through Horizon
|
||||
# handler to the client with verbose message.
|
||||
raise ValueError("Date to must be bigger than date "
|
||||
"from.")
|
||||
# get the time delta in seconds
|
||||
delta = date_to - date_from
|
||||
delta_in_seconds = delta.days * 24 * 3600 + delta.seconds
|
||||
|
||||
period = delta_in_seconds / number_of_samples
|
||||
else:
|
||||
# If some date is missing, just set static window to one day.
|
||||
period = 3600 * 24
|
||||
return period
|
||||
|
||||
|
||||
#TODO(lsmola) push this function to Horizon common then delete this
|
||||
def _calc_date_args(date_from, date_to, date_options):
|
||||
# TODO(lsmola) all timestamps should probably work with
|
||||
# current timezone. And also show the current timezone in chart.
|
||||
if date_options == "other":
|
||||
try:
|
||||
if date_from:
|
||||
date_from = datetime.strptime(date_from,
|
||||
"%Y-%m-%d")
|
||||
else:
|
||||
# TODO(lsmola) there should be probably the date
|
||||
# of the first sample as default, so it correctly
|
||||
# counts the time window. Though I need ordering
|
||||
# and limit of samples to obtain that.
|
||||
pass
|
||||
if date_to:
|
||||
date_to = datetime.strptime(date_to,
|
||||
"%Y-%m-%d")
|
||||
# It return beginning of the day, I want the and of
|
||||
# the day, so i will add one day without a second.
|
||||
date_to = (date_to + timedelta(days=1) -
|
||||
timedelta(seconds=1))
|
||||
else:
|
||||
date_to = timezone.now()
|
||||
except Exception:
|
||||
raise ValueError("The dates haven't been "
|
||||
"recognized")
|
||||
else:
|
||||
try:
|
||||
date_from = timezone.now() - timedelta(days=float(date_options))
|
||||
date_to = timezone.now()
|
||||
except Exception:
|
||||
raise ValueError("The time delta must be an "
|
||||
"integer representing days.")
|
||||
return date_from, date_to
|
||||
|
||||
|
||||
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_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) / len(values)
|
||||
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, start_datetime, end_datetime):
|
||||
return {
|
||||
'series': series,
|
||||
'settings': {
|
||||
'renderer': 'StaticAxes',
|
||||
'yMin': 0,
|
||||
'xMin': start_datetime,
|
||||
'xMax': end_datetime,
|
||||
'higlight_last_point': True,
|
||||
'auto_size': False,
|
||||
'auto_resize': False,
|
||||
'axes_x': False,
|
||||
'axes_y': True,
|
||||
'axes_y_label': False,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def add_barchart_settings(ret, average, used, tooltip_average):
|
||||
ret['settings']['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']
|
||||
}
|
||||
ret['stats'] = {
|
||||
'average': average,
|
||||
'used': used,
|
||||
'tooltip_average': tooltip_average,
|
||||
}
|
||||
return ret
|
||||
|
@ -17,7 +17,7 @@ import heatclient
|
||||
from horizon import tabs
|
||||
|
||||
from tuskar_ui.infrastructure.overcloud import tables
|
||||
from tuskar_ui import utils
|
||||
from tuskar_ui.utils import utils
|
||||
|
||||
|
||||
def _get_role_data(stack, role):
|
||||
|
@ -16,7 +16,7 @@ from django.utils.translation import ugettext_lazy as _
|
||||
import horizon.workflows
|
||||
|
||||
from openstack_dashboard.api import neutron
|
||||
from tuskar_ui import utils
|
||||
from tuskar_ui.utils import utils
|
||||
|
||||
|
||||
def make_field(name, Type, NoEcho, Default, Description, AllowedValues=None,
|
||||
|
0
tuskar_ui/utils/__init__.py
Normal file
0
tuskar_ui/utils/__init__.py
Normal file
200
tuskar_ui/utils/metering.py
Normal file
200
tuskar_ui/utils/metering.py
Normal file
@ -0,0 +1,200 @@
|
||||
# -*- 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 datetime import datetime # noqa
|
||||
from datetime import timedelta # noqa
|
||||
|
||||
from django.utils.http import urlencode
|
||||
from django.utils import timezone
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from horizon import exceptions
|
||||
|
||||
from openstack_dashboard.api import ceilometer
|
||||
from openstack_dashboard.dashboards.admin.metering import views as metering
|
||||
|
||||
|
||||
#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 = _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
|
||||
try:
|
||||
meter_list = [m for m in metering.meter_list(request)
|
||||
if m.name == meter]
|
||||
unit = meter_list[0].unit
|
||||
except Exception:
|
||||
unit = ""
|
||||
if group_by == "resources":
|
||||
# TODO(lsmola) need to implement group_by groups of resources
|
||||
resources = []
|
||||
unit = ""
|
||||
else:
|
||||
ceilometer_usage = ceilometer.CeilometerUsage(request)
|
||||
try:
|
||||
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, unit
|
||||
|
||||
|
||||
#TODO(lsmola) push this function to Horizon common then delete this
|
||||
def _calc_period(date_from, date_to, number_of_samples=400):
|
||||
if date_from and date_to:
|
||||
if date_to < date_from:
|
||||
# TODO(lsmola) propagate the Value error through Horizon
|
||||
# handler to the client with verbose message.
|
||||
raise ValueError("Date to must be bigger than date "
|
||||
"from.")
|
||||
# get the time delta in seconds
|
||||
delta = date_to - date_from
|
||||
delta_in_seconds = delta.days * 24 * 3600 + delta.seconds
|
||||
|
||||
period = delta_in_seconds / number_of_samples
|
||||
else:
|
||||
# If some date is missing, just set static window to one day.
|
||||
period = 3600 * 24
|
||||
return period
|
||||
|
||||
|
||||
#TODO(lsmola) push this function to Horizon common then delete this
|
||||
def _calc_date_args(date_from, date_to, date_options):
|
||||
# TODO(lsmola) all timestamps should probably work with
|
||||
# current timezone. And also show the current timezone in chart.
|
||||
if date_options == "other":
|
||||
try:
|
||||
if date_from:
|
||||
date_from = datetime.strptime(date_from,
|
||||
"%Y-%m-%d")
|
||||
else:
|
||||
# TODO(lsmola) there should be probably the date
|
||||
# of the first sample as default, so it correctly
|
||||
# counts the time window. Though I need ordering
|
||||
# and limit of samples to obtain that.
|
||||
pass
|
||||
if date_to:
|
||||
date_to = datetime.strptime(date_to,
|
||||
"%Y-%m-%d")
|
||||
# It return beginning of the day, I want the and of
|
||||
# the day, so i will add one day without a second.
|
||||
date_to = (date_to + timedelta(days=1) -
|
||||
timedelta(seconds=1))
|
||||
else:
|
||||
date_to = timezone.now()
|
||||
except Exception:
|
||||
raise ValueError("The dates haven't been "
|
||||
"recognized")
|
||||
else:
|
||||
try:
|
||||
date_from = timezone.now() - timedelta(days=float(date_options))
|
||||
date_to = timezone.now()
|
||||
except Exception:
|
||||
raise ValueError("The time delta must be an "
|
||||
"integer representing days.")
|
||||
return date_from, date_to
|
||||
|
||||
|
||||
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_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) / len(values)
|
||||
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, start_datetime, end_datetime):
|
||||
return {
|
||||
'series': series,
|
||||
'settings': {
|
||||
'renderer': 'StaticAxes',
|
||||
'yMin': 0,
|
||||
'xMin': start_datetime,
|
||||
'xMax': end_datetime,
|
||||
'higlight_last_point': True,
|
||||
'auto_size': False,
|
||||
'auto_resize': False,
|
||||
'axes_x': False,
|
||||
'axes_y': True,
|
||||
'axes_y_label': False,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def add_barchart_settings(ret, average, used, tooltip_average):
|
||||
ret['settings']['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']
|
||||
}
|
||||
ret['stats'] = {
|
||||
'average': average,
|
||||
'used': used,
|
||||
'tooltip_average': tooltip_average,
|
||||
}
|
||||
return ret
|
Loading…
x
Reference in New Issue
Block a user