diff --git a/horizon/templates/horizon/common/_limit_summary.html b/horizon/templates/horizon/common/_limit_summary.html index 7774689827..6c75a6448d 100644 --- a/horizon/templates/horizon/common/_limit_summary.html +++ b/horizon/templates/horizon/common/_limit_summary.html @@ -2,53 +2,19 @@

{% trans "Limit Summary" %}

+ {% for quota in charts %}
-
- {% trans "Instances" %}
- {% blocktrans with used=usage.limits.totalInstancesUsed|intcomma available=usage.limits.maxTotalInstances|quotainf|intcomma %}Used {{ used }} of {{ available }} {% endblocktrans %} +
+ {{ quota.name }}
+ {{ quota.text|default:_("Used") }} + {{quota.used|intcomma }} + {% if quota.max|quotainf != '-1' %} + {% trans "of" %} {{ quota.max|quotainf|intcomma }} + {% else %} + {% trans "(No Limit)" %} + {% endif %}
+ {% endfor %} -
-
- {% trans "VCPUs" %}
- {% blocktrans with used=usage.limits.totalCoresUsed|intcomma available=usage.limits.maxTotalCores|quotainf|intcomma %}Used {{ used }} of {{ available }} {% endblocktrans %} -
-
- -
-
- {% trans "RAM" %}
- {% blocktrans with used=usage.limits.totalRAMUsed|mb_float_format available=usage.limits.maxTotalRAMSize|quotainf|mb_float_format %}Used {{ used }} of {{ available }} {% endblocktrans %} -
-
- -
-
- {% trans "Floating IPs" %}
- {% blocktrans with used=usage.limits.totalFloatingIpsUsed|intcomma available=usage.limits.maxTotalFloatingIps|quotainf|intcomma %}Allocated {{ used }} of {{ available }} {% endblocktrans %} -
-
- -
-
- {% trans "Security Groups" %}
- {% blocktrans with used=usage.limits.totalSecurityGroupsUsed|intcomma available=usage.limits.maxSecurityGroups|quotainf|intcomma %}Used {{ used }} of {{ available }} {% endblocktrans %} -
-
- {% if usage.limits.totalVolumesUsed >= 0 %} -
-
- {% trans "Volumes" %}
- {% blocktrans with used=usage.limits.totalVolumesUsed|intcomma available=usage.limits.maxTotalVolumes|quotainf|intcomma %}Used {{ used }} of {{ available }} {% endblocktrans %} -
-
- -
-
- {% trans "Volume Storage" %}
- {% blocktrans with used=usage.limits.totalGigabytesUsed|diskgbformat available=usage.limits.maxTotalVolumeGigabytes|quotainf|diskgbformat %}Used {{ used }} of {{ available }} {% endblocktrans %} -
-
- {% endif %}
diff --git a/horizon/templatetags/horizon.py b/horizon/templatetags/horizon.py index 979bca7148..d5fb283b92 100644 --- a/horizon/templatetags/horizon.py +++ b/horizon/templatetags/horizon.py @@ -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: diff --git a/horizon/test/tests/templatetags.py b/horizon/test/tests/templatetags.py index 4cf74a050e..3dcaa45469 100644 --- a/horizon/test/tests/templatetags.py +++ b/horizon/test/tests/templatetags.py @@ -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, diff --git a/openstack_dashboard/dashboards/project/overview/tests.py b/openstack_dashboard/dashboards/project/overview/tests.py index 785041136d..043f57ba17 100644 --- a/openstack_dashboard/dashboards/project/overview/tests.py +++ b/openstack_dashboard/dashboards/project/overview/tests.py @@ -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)') diff --git a/openstack_dashboard/usage/views.py b/openstack_dashboard/usage/views.py index bd10ad00df..ae4326e666 100644 --- a/openstack_dashboard/usage/views.py +++ b/openstack_dashboard/usage/views.py @@ -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)