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)