Merge "Reduce the default date range on Overview panel to 1 day"
This commit is contained in:
@@ -815,6 +815,22 @@ Used to customize features related to the image service, such as the list of
|
|||||||
supported image formats.
|
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``
|
``IMAGE_CUSTOM_PROPERTY_TITLES``
|
||||||
--------------------------------
|
--------------------------------
|
||||||
|
|
||||||
|
@@ -20,6 +20,7 @@ import datetime
|
|||||||
|
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
from django import http
|
from django import http
|
||||||
|
from django.test.utils import override_settings
|
||||||
from django.utils import encoding
|
from django.utils import encoding
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
|
||||||
@@ -52,21 +53,34 @@ class UsageViewTests(test.BaseAdminViewTests):
|
|||||||
'SimpleTenantUsage', IsA(http.HttpRequest)) \
|
'SimpleTenantUsage', IsA(http.HttpRequest)) \
|
||||||
.AndReturn(nova_stu_enabled)
|
.AndReturn(nova_stu_enabled)
|
||||||
|
|
||||||
|
@override_settings(OVERVIEW_DAYS_RANGE=None)
|
||||||
def test_usage(self):
|
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)
|
self._test_usage(nova_stu_enabled=True)
|
||||||
|
|
||||||
|
@override_settings(OVERVIEW_DAYS_RANGE=None)
|
||||||
def test_usage_disabled(self):
|
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):
|
def test_usage_with_deleted_tenant(self):
|
||||||
self._test_usage(tenant_deleted=True)
|
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)
|
self._stub_api_calls(nova_stu_enabled)
|
||||||
api.nova.extension_supported(
|
api.nova.extension_supported(
|
||||||
'SimpleTenantUsage', IsA(http.HttpRequest)) \
|
'SimpleTenantUsage', IsA(http.HttpRequest)) \
|
||||||
.AndReturn(nova_stu_enabled)
|
.AndReturn(nova_stu_enabled)
|
||||||
now = timezone.now()
|
|
||||||
usage_list = [api.nova.NovaUsage(u) for u in self.usages.list()]
|
usage_list = [api.nova.NovaUsage(u) for u in self.usages.list()]
|
||||||
if tenant_deleted:
|
if tenant_deleted:
|
||||||
api.keystone.tenant_list(IsA(http.HttpRequest)) \
|
api.keystone.tenant_list(IsA(http.HttpRequest)) \
|
||||||
@@ -76,10 +90,11 @@ class UsageViewTests(test.BaseAdminViewTests):
|
|||||||
.AndReturn([self.tenants.list(), False])
|
.AndReturn([self.tenants.list(), False])
|
||||||
|
|
||||||
if nova_stu_enabled:
|
if nova_stu_enabled:
|
||||||
|
start_day, now = self._get_start_end_range(overview_days_range)
|
||||||
api.nova.usage_list(IsA(http.HttpRequest),
|
api.nova.usage_list(IsA(http.HttpRequest),
|
||||||
datetime.datetime(now.year,
|
datetime.datetime(start_day.year,
|
||||||
now.month,
|
start_day.month,
|
||||||
1, 0, 0, 0, 0),
|
start_day.day, 0, 0, 0, 0),
|
||||||
datetime.datetime(now.year,
|
datetime.datetime(now.year,
|
||||||
now.month,
|
now.month,
|
||||||
now.day, 23, 59, 59, 0)) \
|
now.day, 23, 59, 59, 0)) \
|
||||||
@@ -150,26 +165,32 @@ class UsageViewTests(test.BaseAdminViewTests):
|
|||||||
else:
|
else:
|
||||||
self.assertNotContains(res, usage_table, html=True)
|
self.assertNotContains(res, usage_table, html=True)
|
||||||
|
|
||||||
|
@override_settings(OVERVIEW_DAYS_RANGE=None)
|
||||||
def test_usage_csv(self):
|
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)
|
self._test_usage_csv(nova_stu_enabled=True)
|
||||||
|
|
||||||
|
@override_settings(OVERVIEW_DAYS_RANGE=None)
|
||||||
def test_usage_csv_disabled(self):
|
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)
|
self._stub_api_calls(nova_stu_enabled)
|
||||||
api.nova.extension_supported(
|
api.nova.extension_supported(
|
||||||
'SimpleTenantUsage', IsA(http.HttpRequest)) \
|
'SimpleTenantUsage', IsA(http.HttpRequest)) \
|
||||||
.AndReturn(nova_stu_enabled)
|
.AndReturn(nova_stu_enabled)
|
||||||
now = timezone.now()
|
|
||||||
usage_obj = [api.nova.NovaUsage(u) for u in self.usages.list()]
|
usage_obj = [api.nova.NovaUsage(u) for u in self.usages.list()]
|
||||||
api.keystone.tenant_list(IsA(http.HttpRequest)) \
|
api.keystone.tenant_list(IsA(http.HttpRequest)) \
|
||||||
.AndReturn([self.tenants.list(), False])
|
.AndReturn([self.tenants.list(), False])
|
||||||
if nova_stu_enabled:
|
if nova_stu_enabled:
|
||||||
|
start_day, now = self._get_start_end_range(overview_days_range)
|
||||||
api.nova.usage_list(IsA(http.HttpRequest),
|
api.nova.usage_list(IsA(http.HttpRequest),
|
||||||
datetime.datetime(now.year,
|
datetime.datetime(start_day.year,
|
||||||
now.month,
|
start_day.month,
|
||||||
1, 0, 0, 0, 0),
|
start_day.day,
|
||||||
|
0, 0, 0, 0),
|
||||||
datetime.datetime(now.year,
|
datetime.datetime(now.year,
|
||||||
now.month,
|
now.month,
|
||||||
now.day, 23, 59, 59, 0)) \
|
now.day, 23, 59, 59, 0)) \
|
||||||
|
@@ -1553,14 +1553,23 @@ class UsageViewTests(test.BaseAdminViewTests):
|
|||||||
def test_usage_csv_disabled(self):
|
def test_usage_csv_disabled(self):
|
||||||
self._test_usage_csv(nova_stu_enabled=False)
|
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()
|
now = timezone.now()
|
||||||
usage_obj = api.nova.NovaUsage(self.usages.first())
|
usage_obj = api.nova.NovaUsage(self.usages.first())
|
||||||
self._stub_nova_api_calls(nova_stu_enabled)
|
self._stub_nova_api_calls(nova_stu_enabled)
|
||||||
api.nova.extension_supported(
|
api.nova.extension_supported(
|
||||||
'SimpleTenantUsage', IsA(http.HttpRequest)) \
|
'SimpleTenantUsage', IsA(http.HttpRequest)) \
|
||||||
.AndReturn(nova_stu_enabled)
|
.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)
|
end = datetime.datetime(now.year, now.month, now.day, 23, 59, 59, 0)
|
||||||
|
|
||||||
if nova_stu_enabled:
|
if nova_stu_enabled:
|
||||||
|
@@ -23,6 +23,7 @@ from django.conf import settings
|
|||||||
from django.contrib.auth import REDIRECT_FIELD_NAME # noqa
|
from django.contrib.auth import REDIRECT_FIELD_NAME # noqa
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
from django import http
|
from django import http
|
||||||
|
from django.test.utils import override_settings
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
|
||||||
from mox3.mox import IsA # noqa
|
from mox3.mox import IsA # noqa
|
||||||
@@ -42,7 +43,7 @@ class UsageViewTests(test.TestCase):
|
|||||||
'extension_supported')})
|
'extension_supported')})
|
||||||
def _stub_nova_api_calls(self, nova_stu_enabled=True,
|
def _stub_nova_api_calls(self, nova_stu_enabled=True,
|
||||||
tenant_limits_exception=False,
|
tenant_limits_exception=False,
|
||||||
stu_exception=False):
|
stu_exception=False, overview_days_range=None):
|
||||||
api.nova.extension_supported(
|
api.nova.extension_supported(
|
||||||
'SimpleTenantUsage', IsA(http.HttpRequest)) \
|
'SimpleTenantUsage', IsA(http.HttpRequest)) \
|
||||||
.AndReturn(nova_stu_enabled)
|
.AndReturn(nova_stu_enabled)
|
||||||
@@ -58,7 +59,8 @@ class UsageViewTests(test.TestCase):
|
|||||||
.AndReturn(self.limits['absolute'])
|
.AndReturn(self.limits['absolute'])
|
||||||
|
|
||||||
if nova_stu_enabled:
|
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',)})
|
@test.create_stubs({api.cinder: ('tenant_absolute_limits',)})
|
||||||
def _stub_cinder_api_calls(self):
|
def _stub_cinder_api_calls(self):
|
||||||
@@ -81,9 +83,14 @@ class UsageViewTests(test.TestCase):
|
|||||||
api.network.security_group_list(IsA(http.HttpRequest)) \
|
api.network.security_group_list(IsA(http.HttpRequest)) \
|
||||||
.AndReturn(self.q_secgroups.list())
|
.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()
|
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)
|
end = datetime.datetime(now.year, now.month, now.day, 23, 59, 59, 0)
|
||||||
|
|
||||||
if exception:
|
if exception:
|
||||||
@@ -110,14 +117,20 @@ class UsageViewTests(test.TestCase):
|
|||||||
self.assertEqual(usages.limits['maxTotalFloatingIps'],
|
self.assertEqual(usages.limits['maxTotalFloatingIps'],
|
||||||
maxTotalFloatingIps)
|
maxTotalFloatingIps)
|
||||||
|
|
||||||
|
@override_settings(OVERVIEW_DAYS_RANGE=None)
|
||||||
def test_usage(self):
|
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)
|
self._test_usage(nova_stu_enabled=True)
|
||||||
|
|
||||||
|
@override_settings(OVERVIEW_DAYS_RANGE=None)
|
||||||
def test_usage_disabled(self):
|
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):
|
def _test_usage(self, nova_stu_enabled, overview_days_range=1):
|
||||||
self._stub_nova_api_calls(nova_stu_enabled)
|
self._stub_nova_api_calls(nova_stu_enabled,
|
||||||
|
overview_days_range=overview_days_range)
|
||||||
self._stub_neutron_api_calls()
|
self._stub_neutron_api_calls()
|
||||||
self._stub_cinder_api_calls()
|
self._stub_cinder_api_calls()
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
@@ -174,11 +187,16 @@ class UsageViewTests(test.TestCase):
|
|||||||
def test_usage_csv(self):
|
def test_usage_csv(self):
|
||||||
self._test_usage_csv(nova_stu_enabled=True)
|
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):
|
def test_usage_csv_disabled(self):
|
||||||
self._test_usage_csv(nova_stu_enabled=False)
|
self._test_usage_csv(nova_stu_enabled=False)
|
||||||
|
|
||||||
def _test_usage_csv(self, nova_stu_enabled=True):
|
def _test_usage_csv(self, nova_stu_enabled=True, overview_days_range=None):
|
||||||
self._stub_nova_api_calls(nova_stu_enabled)
|
self._stub_nova_api_calls(nova_stu_enabled,
|
||||||
|
overview_days_range=overview_days_range)
|
||||||
self._stub_neutron_api_calls()
|
self._stub_neutron_api_calls()
|
||||||
self._stub_cinder_api_calls()
|
self._stub_cinder_api_calls()
|
||||||
self.mox.ReplayAll()
|
self.mox.ReplayAll()
|
||||||
|
@@ -771,3 +771,8 @@ REST_API_REQUIRED_SETTINGS = ['OPENSTACK_HYPERVISOR_FEATURES',
|
|||||||
# " [%(http_status)s] [%(param)s]"),
|
# " [%(http_status)s] [%(param)s]"),
|
||||||
#}
|
#}
|
||||||
|
|
||||||
|
# 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 should be used to limit the amount
|
||||||
|
# of data fetched by default when rendering the Overview panel.
|
||||||
|
#OVERVIEW_DAYS_RANGE = 1
|
||||||
|
@@ -14,6 +14,7 @@ from __future__ import division
|
|||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
@@ -40,6 +41,14 @@ class BaseUsage(object):
|
|||||||
def today(self):
|
def today(self):
|
||||||
return timezone.now()
|
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
|
@staticmethod
|
||||||
def get_start(year, month, day):
|
def get_start(year, month, day):
|
||||||
start = datetime.datetime(year, month, day, 0, 0, 0)
|
start = datetime.datetime(year, month, day, 0, 0, 0)
|
||||||
@@ -57,7 +66,8 @@ class BaseUsage(object):
|
|||||||
|
|
||||||
def get_date_range(self):
|
def get_date_range(self):
|
||||||
if not hasattr(self, "start") or not hasattr(self, "end"):
|
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)
|
args_end = (self.today.year, self.today.month, self.today.day)
|
||||||
form = self.get_form()
|
form = self.get_form()
|
||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
@@ -73,14 +83,13 @@ class BaseUsage(object):
|
|||||||
messages.error(self.request,
|
messages.error(self.request,
|
||||||
_("Invalid date format: "
|
_("Invalid date format: "
|
||||||
"Using today as default."))
|
"Using today as default."))
|
||||||
self.start = self.get_start(*args_start)
|
self.start = self.get_start(*args_start)
|
||||||
self.end = self.get_end(*args_end)
|
self.end = self.get_end(*args_end)
|
||||||
return self.start, self.end
|
return self.start, self.end
|
||||||
|
|
||||||
def init_form(self):
|
def init_form(self):
|
||||||
today = datetime.date.today()
|
self.start = self.first_day
|
||||||
self.start = datetime.date(day=1, month=today.month, year=today.year)
|
self.end = self.today.date()
|
||||||
self.end = today
|
|
||||||
|
|
||||||
return self.start, self.end
|
return self.start, self.end
|
||||||
|
|
||||||
|
@@ -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
|
Reference in New Issue
Block a user