From a6c5ab6cadaf6c11b3e153f7a0f6e9397cd0826f Mon Sep 17 00:00:00 2001 From: Rob Raymond Date: Mon, 10 Feb 2014 17:23:46 -0700 Subject: [PATCH] Refactor large method into 4 methods In trying to reuse some of the code in views, I realized that the get method for SampleView is quite long. This change breaks this method into 3 functions. The get method now is responsible for parsing HTTP arguments and formatting AJAX response. The other functionality has been pulled out. One of these functions (query_data) can be used by other views in the future. Change-Id: I9a71bf62eb871ac9c082208e991402f0c700c668 Closes-Bug: #1278654 --- .../dashboards/admin/metering/views.py | 288 ++++++++++-------- 1 file changed, 155 insertions(+), 133 deletions(-) diff --git a/openstack_dashboard/dashboards/admin/metering/views.py b/openstack_dashboard/dashboards/admin/metering/views.py index 029454a368..d4fb1456a2 100644 --- a/openstack_dashboard/dashboards/admin/metering/views.py +++ b/openstack_dashboard/dashboards/admin/metering/views.py @@ -70,140 +70,20 @@ class SamplesView(TemplateView): date_from = request.GET.get('date_from', None) date_to = request.GET.get('date_to', None) stats_attr = request.GET.get('stats_attr', 'avg') + group_by = request.GET.get('group_by', None) - # 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 = datetime.now() - except Exception: - raise ValueError("The dates haven't been " - "recognized") - else: - try: - date_from = datetime.now() - timedelta(days=int(date_options)) - date_to = datetime.now() - except Exception: - raise ValueError("The time delta must be an " - "integer representing days.") - - 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 - if delta.days <= 0: - # it's one day - delta_in_seconds = 3600 * 24 - else: - delta_in_seconds = delta.days * 24 * 3600 + delta.seconds - # Lets always show 400 samples in the chart. Know that it is - # maximum amount of samples and it can be lower. - number_of_samples = 400 - period = delta_in_seconds / number_of_samples - else: - # If some date is missing, just set static window to one day. - period = 3600 * 24 - - 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 ceilometer.meter_list(request) - if m.name == meter] - unit = meter_list[0].unit - except Exception: - unit = "" - - if request.GET.get('group_by', None) == "project": - try: - tenants, more = api.keystone.tenant_list( - request, - domain=None, - paginate=False) - except Exception: - tenants = [] - exceptions.handle(request, - _('Unable to retrieve tenant list.')) - queries = {} - for tenant in tenants: - tenant_query = [{ - "field": "project_id", - "op": "eq", - "value": tenant.id}] - - queries[tenant.name] = tenant_query - - ceilometer_usage = ceilometer.CeilometerUsage(request) - resources = ceilometer_usage.resource_aggregates_with_statistics( - queries, [meter], period=period, stats_attr=None, - additional_query=additional_query) - - series = self._series_for_meter(resources, - 'id', - meter_name, - stats_attr, - unit) - else: - query = [] - - def filter_by_meter_name(resource): - """Function for filtering of the list of resources. - - Will pick the right resources according to currently selected - meter. - """ - for link in resource.links: - if link['rel'] == meter: - # If resource has the currently chosen meter. - return True - return False - - ceilometer_usage = ceilometer.CeilometerUsage(request) - try: - resources = ceilometer_usage.resources_with_statistics( - query, [meter], period=period, stats_attr=None, - additional_query=additional_query, - filter_func=filter_by_meter_name) - except Exception: - resources = [] - exceptions.handle(request, - _('Unable to retrieve statistics.')) - - series = self._series_for_meter(resources, - 'resource_id', - meter_name, - stats_attr, - unit) + resources, unit = query_data(request, + date_from, + date_to, + date_options, + group_by, + meter) + resource_name = 'id' if group_by == "project" else 'resource_id' + series = self._series_for_meter(resources, + resource_name, + meter_name, + stats_attr, + unit) ret = {} ret['series'] = series @@ -211,3 +91,145 @@ class SamplesView(TemplateView): return HttpResponse(json.dumps(ret), content_type='application/json') + + +def _calc_period(date_from, date_to): + 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 + if delta.days <= 0: + # it's one day + delta_in_seconds = 3600 * 24 + else: + delta_in_seconds = delta.days * 24 * 3600 + delta.seconds + # Lets always show 400 samples in the chart. Know that it is + # maximum amount of samples and it can be lower. + number_of_samples = 400 + 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 + + +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 = datetime.now() + except Exception: + raise ValueError("The dates haven't been " + "recognized") + else: + try: + date_from = datetime.now() - timedelta(days=int(date_options)) + date_to = datetime.now() + except Exception: + raise ValueError("The time delta must be an " + "integer representing days.") + return date_from, date_to + + +def query_data(request, + date_from, + date_to, + date_options, + group_by, + meter, + period=None): + date_from, date_to = _calc_date_args(date_from, + date_to, + date_options) + if not period: + period = _calc_period(date_from, date_to) + 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 ceilometer.meter_list(request) + if m.name == meter] + unit = meter_list[0].unit + except Exception: + unit = "" + if group_by == "project": + try: + tenants, more = api.keystone.tenant_list( + request, + domain=None, + paginate=False) + except Exception: + tenants = [] + exceptions.handle(request, + _('Unable to retrieve tenant list.')) + queries = {} + for tenant in tenants: + tenant_query = [{ + "field": "project_id", + "op": "eq", + "value": tenant.id}] + + queries[tenant.name] = tenant_query + + ceilometer_usage = ceilometer.CeilometerUsage(request) + resources = ceilometer_usage.resource_aggregates_with_statistics( + queries, [meter], period=period, stats_attr=None, + additional_query=additional_query) + + else: + query = [] + + def filter_by_meter_name(resource): + """Function for filtering of the list of resources. + + Will pick the right resources according to currently selected + meter. + """ + for link in resource.links: + if link['rel'] == meter: + # If resource has the currently chosen meter. + return True + return False + + ceilometer_usage = ceilometer.CeilometerUsage(request) + try: + resources = ceilometer_usage.resources_with_statistics( + query, [meter], period=period, stats_attr=None, + additional_query=additional_query, + filter_func=filter_by_meter_name) + except Exception: + resources = [] + exceptions.handle(request, + _('Unable to retrieve statistics.')) + return resources, unit