Refactor quota limit summary template
Refactor the quota limit summary template to allow easier customisation. Also change it so that it removes the 'of' when there is no quota limits in place so that it just reads Used 'x' (No Limit). Added tests for checking usage['charts'] is in the context and that (No Limit) is present when there is an infinite quota on the page. Change-Id: Iba62ca89e53f0d6b9c583e4cc450e853c18ba107 Closes-bug: 1439717
This commit is contained in:
parent
6d33c076bf
commit
286245b423
@ -2,53 +2,19 @@
|
||||
|
||||
<div class="quota-dynamic">
|
||||
<h3 class="quota-heading">{% trans "Limit Summary" %}</h3>
|
||||
{% for quota in charts %}
|
||||
<div class="d3_quota_bar">
|
||||
<div class="d3_pie_chart_usage" data-used="{% quotapercent usage.limits.totalInstancesUsed usage.limits.maxTotalInstances %}"></div>
|
||||
<strong>{% trans "Instances" %} <br />
|
||||
{% blocktrans with used=usage.limits.totalInstancesUsed|intcomma available=usage.limits.maxTotalInstances|quotainf|intcomma %}Used <span> {{ used }} </span> of <span> {{ available }} </span>{% endblocktrans %}
|
||||
<div class="d3_pie_chart_usage" data-used="{% quotapercent quota.used quota.max %}"></div>
|
||||
<strong> {{ quota.name }} <br />
|
||||
{{ quota.text|default:_("Used") }}
|
||||
<span> {{quota.used|intcomma }} </span>
|
||||
{% if quota.max|quotainf != '-1' %}
|
||||
{% trans "of" %} <span> {{ quota.max|quotainf|intcomma }} </span>
|
||||
{% else %}
|
||||
<span> {% trans "(No Limit)" %} </span>
|
||||
{% endif %}
|
||||
</strong>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
<div class="d3_quota_bar">
|
||||
<div class="d3_pie_chart_usage" data-used="{% quotapercent usage.limits.totalCoresUsed usage.limits.maxTotalCores %}"></div>
|
||||
<strong>{% trans "VCPUs" %} <br />
|
||||
{% blocktrans with used=usage.limits.totalCoresUsed|intcomma available=usage.limits.maxTotalCores|quotainf|intcomma %}Used <span> {{ used }} </span> of <span> {{ available }} </span>{% endblocktrans %}
|
||||
</strong>
|
||||
</div>
|
||||
|
||||
<div class="d3_quota_bar">
|
||||
<div class="d3_pie_chart_usage" data-used="{% quotapercent usage.limits.totalRAMUsed usage.limits.maxTotalRAMSize %}"></div>
|
||||
<strong>{% trans "RAM" %} <br />
|
||||
{% blocktrans with used=usage.limits.totalRAMUsed|mb_float_format available=usage.limits.maxTotalRAMSize|quotainf|mb_float_format %}Used <span> {{ used }} </span> of <span> {{ available }} </span>{% endblocktrans %}
|
||||
</strong>
|
||||
</div>
|
||||
|
||||
<div class="d3_quota_bar">
|
||||
<div class="d3_pie_chart_usage" data-used="{% quotapercent usage.limits.totalFloatingIpsUsed usage.limits.maxTotalFloatingIps %}"></div>
|
||||
<strong>{% trans "Floating IPs" %} <br />
|
||||
{% blocktrans with used=usage.limits.totalFloatingIpsUsed|intcomma available=usage.limits.maxTotalFloatingIps|quotainf|intcomma %}Allocated <span> {{ used }} </span> of <span> {{ available }} </span>{% endblocktrans %}
|
||||
</strong>
|
||||
</div>
|
||||
|
||||
<div class="d3_quota_bar">
|
||||
<div class="d3_pie_chart_usage" data-used="{% quotapercent usage.limits.totalSecurityGroupsUsed usage.limits.maxSecurityGroups %}"></div>
|
||||
<strong>{% trans "Security Groups" %} <br />
|
||||
{% blocktrans with used=usage.limits.totalSecurityGroupsUsed|intcomma available=usage.limits.maxSecurityGroups|quotainf|intcomma %}Used <span> {{ used }} </span> of <span> {{ available }} </span>{% endblocktrans %}
|
||||
</strong>
|
||||
</div>
|
||||
{% if usage.limits.totalVolumesUsed >= 0 %}
|
||||
<div class="d3_quota_bar">
|
||||
<div class="d3_pie_chart_usage" data-used="{% quotapercent usage.limits.totalVolumesUsed usage.limits.maxTotalVolumes %}"></div>
|
||||
<strong>{% trans "Volumes" %} <br />
|
||||
{% blocktrans with used=usage.limits.totalVolumesUsed|intcomma available=usage.limits.maxTotalVolumes|quotainf|intcomma %}Used <span> {{ used }} </span> of <span> {{ available }} </span>{% endblocktrans %}
|
||||
</strong>
|
||||
</div>
|
||||
|
||||
<div class="d3_quota_bar">
|
||||
<div class="d3_pie_chart_usage" data-used="{% quotapercent usage.limits.totalGigabytesUsed usage.limits.maxTotalVolumeGigabytes %}"></div>
|
||||
<strong>{% trans "Volume Storage" %} <br />
|
||||
{% blocktrans with used=usage.limits.totalGigabytesUsed|diskgbformat available=usage.limits.maxTotalVolumeGigabytes|quotainf|diskgbformat %}Used <span> {{ used }} </span> of <span> {{ available }} </span>{% endblocktrans %}
|
||||
</strong>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
@ -134,7 +134,7 @@ def horizon_dashboard_nav(context):
|
||||
@register.filter
|
||||
def quota(val, units=None):
|
||||
if val == float("inf"):
|
||||
return _("No Limit")
|
||||
return _("(No Limit)")
|
||||
elif units is not None:
|
||||
return "%s %s %s" % (val, force_text(units),
|
||||
force_text(_("Available")))
|
||||
@ -145,7 +145,7 @@ def quota(val, units=None):
|
||||
@register.filter
|
||||
def quotainf(val, units=None):
|
||||
if val == float("inf"):
|
||||
return _("No Limit")
|
||||
return '-1'
|
||||
elif units is not None:
|
||||
return "%s %s" % (val, units)
|
||||
else:
|
||||
|
@ -104,7 +104,7 @@ class TemplateTagTests(test.TestCase):
|
||||
text = ('{{ test.val1|quota:"TB" }}#{{ test.val2|quota }}#'
|
||||
'{{ test.val3|quota }}')
|
||||
|
||||
expected = u' 100 TB Available#1000 Available#No Limit'
|
||||
expected = u' 100 TB Available#1000 Available#(No Limit)'
|
||||
|
||||
rendered_str = self.render_template(tag_require='horizon',
|
||||
template_text=text,
|
||||
|
@ -240,13 +240,16 @@ class UsageViewTests(test.TestCase):
|
||||
.AndReturn(self.neutron_quotas.first())
|
||||
self.mox.ReplayAll()
|
||||
|
||||
self._test_usage_with_neutron_check(neutron_sg_enabled)
|
||||
self._test_usage_with_neutron_check(neutron_sg_enabled,
|
||||
neutron_fip_enabled)
|
||||
|
||||
def _test_usage_with_neutron_check(self, neutron_sg_enabled=True,
|
||||
neutron_fip_expected=True,
|
||||
max_fip_expected=50,
|
||||
max_sg_expected=20):
|
||||
res = self.client.get(reverse('horizon:project:overview:index'))
|
||||
self.assertContains(res, 'Floating IPs')
|
||||
if neutron_fip_expected:
|
||||
self.assertContains(res, 'Floating IPs')
|
||||
self.assertContains(res, 'Security Groups')
|
||||
|
||||
res_limits = res.context['usage'].limits
|
||||
@ -264,7 +267,8 @@ class UsageViewTests(test.TestCase):
|
||||
api.neutron.is_extension_supported(
|
||||
IsA(http.HttpRequest), 'quotas').AndRaise(self.exceptions.neutron)
|
||||
self.mox.ReplayAll()
|
||||
self._test_usage_with_neutron_check(max_fip_expected=float("inf"),
|
||||
self._test_usage_with_neutron_check(neutron_fip_expected=False,
|
||||
max_fip_expected=float("inf"),
|
||||
max_sg_expected=float("inf"))
|
||||
|
||||
@test.update_settings(OPENSTACK_NEUTRON_NETWORK={'enable_quotas': True})
|
||||
@ -276,7 +280,8 @@ class UsageViewTests(test.TestCase):
|
||||
IsA(http.HttpRequest),
|
||||
'security-group').AndRaise(self.exceptions.neutron)
|
||||
self.mox.ReplayAll()
|
||||
self._test_usage_with_neutron_check(max_fip_expected=float("inf"),
|
||||
self._test_usage_with_neutron_check(neutron_fip_expected=False,
|
||||
max_fip_expected=float("inf"),
|
||||
max_sg_expected=float("inf"))
|
||||
|
||||
def test_usage_with_cinder(self):
|
||||
@ -309,3 +314,23 @@ class UsageViewTests(test.TestCase):
|
||||
self.assertEqual(usages.limits['maxTotalVolumeGigabytes'], 1000)
|
||||
else:
|
||||
self.assertNotIn('totalVolumesUsed', usages.limits)
|
||||
|
||||
def _test_usage_charts(self):
|
||||
self._stub_nova_api_calls(False)
|
||||
self._stub_neutron_api_calls()
|
||||
self._stub_cinder_api_calls()
|
||||
self.mox.ReplayAll()
|
||||
|
||||
return self.client.get(reverse('horizon:project:overview:index'))
|
||||
|
||||
def test_usage_charts_created(self):
|
||||
res = self._test_usage_charts()
|
||||
self.assertTrue('charts' in res.context)
|
||||
|
||||
def test_usage_charts_infinite_quota(self):
|
||||
res = self._test_usage_charts()
|
||||
|
||||
max_floating_ips = res.context['usage'].limits['maxTotalFloatingIps']
|
||||
self.assertEqual(max_floating_ips, float("inf"))
|
||||
|
||||
self.assertContains(res, '(No Limit)')
|
||||
|
@ -60,6 +60,36 @@ class UsageView(tables.DataTableView):
|
||||
context['table'].kwargs['usage'] = self.usage
|
||||
context['form'] = self.usage.form
|
||||
context['usage'] = self.usage
|
||||
context['charts'] = []
|
||||
|
||||
# (Used key, Max key, Human Readable Name, text to display when
|
||||
# describing the quota by default it is 'Used')
|
||||
types = [("totalInstancesUsed", "maxTotalInstances", _("Instances")),
|
||||
("totalCoresUsed", "maxTotalCores", _("VCPUs")),
|
||||
("totalRAMUsed", "maxTotalRAMSize", _("RAM")),
|
||||
("totalFloatingIpsUsed", "maxTotalFloatingIps",
|
||||
"Floating IPs", _("Allocated")),
|
||||
("totalSecurityGroupsUsed", "maxSecurityGroups",
|
||||
_("Security Groups"))]
|
||||
# Check for volume usage
|
||||
if 'totalVolumesUsed' in self.usage.limits and self.usage.limits[
|
||||
'totalVolumesUsed'] >= 0:
|
||||
types.append(("totalVolumesUsed", "maxTotalVolumes",
|
||||
_("Volumes")))
|
||||
types.append(("totalGigabytesUsed", "maxTotalVolumeGigabytes",
|
||||
_("Volume Storage")))
|
||||
for t in types:
|
||||
if t[0] in self.usage.limits and t[1] in self.usage.limits:
|
||||
text = False
|
||||
if len(t) > 3:
|
||||
text = t[3]
|
||||
context['charts'].append({
|
||||
'name': t[2],
|
||||
'used': self.usage.limits[t[0]],
|
||||
'max': self.usage.limits[t[1]],
|
||||
'text': text
|
||||
})
|
||||
|
||||
try:
|
||||
context['simple_tenant_usage_enabled'] = \
|
||||
api.nova.extension_supported('SimpleTenantUsage', self.request)
|
||||
|
Loading…
x
Reference in New Issue
Block a user