diff --git a/doc/source/topics/settings.rst b/doc/source/topics/settings.rst index 281dbc61f2..4f912fb09d 100644 --- a/doc/source/topics/settings.rst +++ b/doc/source/topics/settings.rst @@ -815,6 +815,22 @@ Used to customize features related to the image service, such as the list of supported image formats. +``OVERVIEW_DAYS_RANGE`` +----------------------- + +.. versionadded:: 10.0.0(Newton) + +Default:: ``1`` + +When set to an integer N (as by default), the start date in the Overview panel +meters will be today minus N days. This setting is used to limit the amount of +data fetched by default when rendering the Overview panel. If set to ``None`` +(which corresponds to the behavior in past Horizon versions), the start date +will be from the beginning of the current month until the current date. The +legacy behaviour is not recommended for large deployments as Horizon suffers +significant lags in this case. + + ``IMAGE_CUSTOM_PROPERTY_TITLES`` -------------------------------- diff --git a/openstack_dashboard/dashboards/admin/overview/tests.py b/openstack_dashboard/dashboards/admin/overview/tests.py index 3e69613062..2281abfe6e 100644 --- a/openstack_dashboard/dashboards/admin/overview/tests.py +++ b/openstack_dashboard/dashboards/admin/overview/tests.py @@ -20,6 +20,7 @@ import datetime from django.core.urlresolvers import reverse from django import http +from django.test.utils import override_settings from django.utils import encoding from django.utils import timezone @@ -52,21 +53,34 @@ class UsageViewTests(test.BaseAdminViewTests): 'SimpleTenantUsage', IsA(http.HttpRequest)) \ .AndReturn(nova_stu_enabled) + @override_settings(OVERVIEW_DAYS_RANGE=None) def test_usage(self): + self._test_usage(nova_stu_enabled=True, overview_days_range=None) + + def test_usage_1_day(self): self._test_usage(nova_stu_enabled=True) + @override_settings(OVERVIEW_DAYS_RANGE=None) def test_usage_disabled(self): - self._test_usage(nova_stu_enabled=False) + self._test_usage(nova_stu_enabled=False, overview_days_range=None) def test_usage_with_deleted_tenant(self): self._test_usage(tenant_deleted=True) - def _test_usage(self, nova_stu_enabled=True, tenant_deleted=False): + def _get_start_end_range(self, overview_days_range): + now = timezone.now() + if overview_days_range: + start_day = now - datetime.timedelta(days=overview_days_range) + else: + start_day = datetime.date(now.year, now.month, 1) + return start_day, now + + def _test_usage(self, nova_stu_enabled=True, tenant_deleted=False, + overview_days_range=1): self._stub_api_calls(nova_stu_enabled) api.nova.extension_supported( 'SimpleTenantUsage', IsA(http.HttpRequest)) \ .AndReturn(nova_stu_enabled) - now = timezone.now() usage_list = [api.nova.NovaUsage(u) for u in self.usages.list()] if tenant_deleted: api.keystone.tenant_list(IsA(http.HttpRequest)) \ @@ -76,10 +90,11 @@ class UsageViewTests(test.BaseAdminViewTests): .AndReturn([self.tenants.list(), False]) if nova_stu_enabled: + start_day, now = self._get_start_end_range(overview_days_range) api.nova.usage_list(IsA(http.HttpRequest), - datetime.datetime(now.year, - now.month, - 1, 0, 0, 0, 0), + datetime.datetime(start_day.year, + start_day.month, + start_day.day, 0, 0, 0, 0), datetime.datetime(now.year, now.month, now.day, 23, 59, 59, 0)) \ @@ -150,26 +165,32 @@ class UsageViewTests(test.BaseAdminViewTests): else: self.assertNotContains(res, usage_table, html=True) + @override_settings(OVERVIEW_DAYS_RANGE=None) def test_usage_csv(self): + self._test_usage_csv(nova_stu_enabled=True, overview_days_range=None) + + def test_usage_csv_1_day(self): self._test_usage_csv(nova_stu_enabled=True) + @override_settings(OVERVIEW_DAYS_RANGE=None) def test_usage_csv_disabled(self): - self._test_usage_csv(nova_stu_enabled=False) + self._test_usage_csv(nova_stu_enabled=False, overview_days_range=None) - def _test_usage_csv(self, nova_stu_enabled=True): + def _test_usage_csv(self, nova_stu_enabled=True, overview_days_range=1): self._stub_api_calls(nova_stu_enabled) api.nova.extension_supported( 'SimpleTenantUsage', IsA(http.HttpRequest)) \ .AndReturn(nova_stu_enabled) - now = timezone.now() usage_obj = [api.nova.NovaUsage(u) for u in self.usages.list()] api.keystone.tenant_list(IsA(http.HttpRequest)) \ .AndReturn([self.tenants.list(), False]) if nova_stu_enabled: + start_day, now = self._get_start_end_range(overview_days_range) api.nova.usage_list(IsA(http.HttpRequest), - datetime.datetime(now.year, - now.month, - 1, 0, 0, 0, 0), + datetime.datetime(start_day.year, + start_day.month, + start_day.day, + 0, 0, 0, 0), datetime.datetime(now.year, now.month, now.day, 23, 59, 59, 0)) \ diff --git a/openstack_dashboard/dashboards/identity/projects/tests.py b/openstack_dashboard/dashboards/identity/projects/tests.py index 7562821ccc..b321b810f6 100644 --- a/openstack_dashboard/dashboards/identity/projects/tests.py +++ b/openstack_dashboard/dashboards/identity/projects/tests.py @@ -1553,14 +1553,23 @@ class UsageViewTests(test.BaseAdminViewTests): def test_usage_csv_disabled(self): self._test_usage_csv(nova_stu_enabled=False) - def _test_usage_csv(self, nova_stu_enabled=True): + @override_settings(OVERVIEW_DAYS_RANGE=1) + def test_usage_csv_1_day(self): + self._test_usage_csv(nova_stu_enabled=True, overview_days_range=1) + + def _test_usage_csv(self, nova_stu_enabled=True, overview_days_range=None): now = timezone.now() usage_obj = api.nova.NovaUsage(self.usages.first()) self._stub_nova_api_calls(nova_stu_enabled) api.nova.extension_supported( 'SimpleTenantUsage', IsA(http.HttpRequest)) \ .AndReturn(nova_stu_enabled) - start = datetime.datetime(now.year, now.month, 1, 0, 0, 0, 0) + if overview_days_range: + start_day = now - datetime.timedelta(days=overview_days_range) + else: + start_day = datetime.date(now.year, now.month, 1) + start = datetime.datetime(start_day.year, start_day.month, + start_day.day, 0, 0, 0, 0) end = datetime.datetime(now.year, now.month, now.day, 23, 59, 59, 0) if nova_stu_enabled: diff --git a/openstack_dashboard/dashboards/project/overview/tests.py b/openstack_dashboard/dashboards/project/overview/tests.py index 7af37ae659..fb6d66021a 100644 --- a/openstack_dashboard/dashboards/project/overview/tests.py +++ b/openstack_dashboard/dashboards/project/overview/tests.py @@ -23,6 +23,7 @@ from django.conf import settings from django.contrib.auth import REDIRECT_FIELD_NAME # noqa from django.core.urlresolvers import reverse from django import http +from django.test.utils import override_settings from django.utils import timezone from mox3.mox import IsA # noqa @@ -42,7 +43,7 @@ class UsageViewTests(test.TestCase): 'extension_supported')}) def _stub_nova_api_calls(self, nova_stu_enabled=True, tenant_limits_exception=False, - stu_exception=False): + stu_exception=False, overview_days_range=None): api.nova.extension_supported( 'SimpleTenantUsage', IsA(http.HttpRequest)) \ .AndReturn(nova_stu_enabled) @@ -58,7 +59,8 @@ class UsageViewTests(test.TestCase): .AndReturn(self.limits['absolute']) if nova_stu_enabled: - self._nova_stu_enabled(stu_exception) + self._nova_stu_enabled(stu_exception, + overview_days_range=overview_days_range) @test.create_stubs({api.cinder: ('tenant_absolute_limits',)}) def _stub_cinder_api_calls(self): @@ -81,9 +83,14 @@ class UsageViewTests(test.TestCase): api.network.security_group_list(IsA(http.HttpRequest)) \ .AndReturn(self.q_secgroups.list()) - def _nova_stu_enabled(self, exception=False): + def _nova_stu_enabled(self, exception=False, overview_days_range=1): now = timezone.now() - start = datetime.datetime(now.year, now.month, 1, 0, 0, 0, 0) + if overview_days_range: + start_day = now - datetime.timedelta(days=overview_days_range) + else: + start_day = datetime.date(now.year, now.month, 1) + start = datetime.datetime(start_day.year, start_day.month, + start_day.day, 0, 0, 0, 0) end = datetime.datetime(now.year, now.month, now.day, 23, 59, 59, 0) if exception: @@ -110,14 +117,20 @@ class UsageViewTests(test.TestCase): self.assertEqual(usages.limits['maxTotalFloatingIps'], maxTotalFloatingIps) + @override_settings(OVERVIEW_DAYS_RANGE=None) def test_usage(self): + self._test_usage(nova_stu_enabled=True, overview_days_range=None) + + def test_usage_1_day(self): self._test_usage(nova_stu_enabled=True) + @override_settings(OVERVIEW_DAYS_RANGE=None) def test_usage_disabled(self): - self._test_usage(nova_stu_enabled=False) + self._test_usage(nova_stu_enabled=False, overview_days_range=None) - def _test_usage(self, nova_stu_enabled): - self._stub_nova_api_calls(nova_stu_enabled) + def _test_usage(self, nova_stu_enabled, overview_days_range=1): + self._stub_nova_api_calls(nova_stu_enabled, + overview_days_range=overview_days_range) self._stub_neutron_api_calls() self._stub_cinder_api_calls() self.mox.ReplayAll() @@ -174,11 +187,16 @@ class UsageViewTests(test.TestCase): def test_usage_csv(self): self._test_usage_csv(nova_stu_enabled=True) + @override_settings(OVERVIEW_DAYS_RANGE=1) + def test_usage_csv_1_day(self): + self._test_usage_csv(nova_stu_enabled=True, overview_days_range=1) + def test_usage_csv_disabled(self): self._test_usage_csv(nova_stu_enabled=False) - def _test_usage_csv(self, nova_stu_enabled=True): - self._stub_nova_api_calls(nova_stu_enabled) + def _test_usage_csv(self, nova_stu_enabled=True, overview_days_range=None): + self._stub_nova_api_calls(nova_stu_enabled, + overview_days_range=overview_days_range) self._stub_neutron_api_calls() self._stub_cinder_api_calls() self.mox.ReplayAll() diff --git a/openstack_dashboard/local/local_settings.py.example b/openstack_dashboard/local/local_settings.py.example index d3133e9d3d..807354891e 100644 --- a/openstack_dashboard/local/local_settings.py.example +++ b/openstack_dashboard/local/local_settings.py.example @@ -771,3 +771,8 @@ REST_API_REQUIRED_SETTINGS = ['OPENSTACK_HYPERVISOR_FEATURES', # " [%(http_status)s] [%(param)s]"), #} +# The default date range in the Overview panel meters - either minus N +# days (if the value is integer N), or from the beginning of the current month +# until today (if set to None). This setting should be used to limit the amount +# of data fetched by default when rendering the Overview panel. +#OVERVIEW_DAYS_RANGE = 1 diff --git a/openstack_dashboard/usage/base.py b/openstack_dashboard/usage/base.py index 6fb2332f89..b7b2f6b00e 100644 --- a/openstack_dashboard/usage/base.py +++ b/openstack_dashboard/usage/base.py @@ -14,6 +14,7 @@ from __future__ import division import datetime +from django.conf import settings from django.utils import timezone from django.utils.translation import ugettext_lazy as _ @@ -40,6 +41,14 @@ class BaseUsage(object): def today(self): return timezone.now() + @property + def first_day(self): + days_range = getattr(settings, 'OVERVIEW_DAYS_RANGE', 1) + if days_range: + return self.today.date() - datetime.timedelta(days=days_range) + else: + return datetime.date(self.today.year, self.today.month, 1) + @staticmethod def get_start(year, month, day): start = datetime.datetime(year, month, day, 0, 0, 0) @@ -57,7 +66,8 @@ class BaseUsage(object): def get_date_range(self): if not hasattr(self, "start") or not hasattr(self, "end"): - args_start = (self.today.year, self.today.month, 1) + args_start = (self.first_day.year, self.first_day.month, + self.first_day.day) args_end = (self.today.year, self.today.month, self.today.day) form = self.get_form() if form.is_valid(): @@ -73,14 +83,13 @@ class BaseUsage(object): messages.error(self.request, _("Invalid date format: " "Using today as default.")) - self.start = self.get_start(*args_start) - self.end = self.get_end(*args_end) + self.start = self.get_start(*args_start) + self.end = self.get_end(*args_end) return self.start, self.end def init_form(self): - today = datetime.date.today() - self.start = datetime.date(day=1, month=today.month, year=today.year) - self.end = today + self.start = self.first_day + self.end = self.today.date() return self.start, self.end diff --git a/releasenotes/notes/setting-OVERVIEW_DAYS_RANGE-9b87e8b077952a32.yaml b/releasenotes/notes/setting-OVERVIEW_DAYS_RANGE-9b87e8b077952a32.yaml new file mode 100644 index 0000000000..2038222230 --- /dev/null +++ b/releasenotes/notes/setting-OVERVIEW_DAYS_RANGE-9b87e8b077952a32.yaml @@ -0,0 +1,11 @@ +--- +features: + - Add a new setting OVERVIEW_DAYS_RANGE. + It defines the default date range in the Overview panel meters - either + today minus N days (if the value is integer N), or from the beginning of + the current month until today (if set to None). This setting is be used to + limit the amount of data fetched by default when rendering the Overview + panel. The default value is 1, which differs from the past behaviour, since + it caused serious lags on large deployments. +fixes: + - https://bugs.launchpad.net/horizon/+bug/1508571