Browse Source

quota: Use network quota field names consistently

Previously neutron quota names and nova-network quota names are
mixly used and this makes the readability terrible.
We no longer supports nova-network, so it looks simple to use
neutron quota names consistently.

Neutron quota names use singular form and it is different
from nova and cinder (which adopt plural form as quota names).
Although it might be confusing, the mixed usage is much worse.
Some wrapper layer may address singular vs plural form issue,
but it can be solved later. Let's use neutron quota names
directly now to simplify the code.

blueprint make-quotas-great-again
Change-Id: Ie31414ada34cbdbd046063b512d3cef0a6e68acf
tags/13.0.0.0b3
Akihiro Motoki 2 years ago
parent
commit
1340904d47
23 changed files with 160 additions and 231 deletions
  1. +2
    -2
      openstack_dashboard/dashboards/admin/networks/ports/tables.py
  2. +3
    -3
      openstack_dashboard/dashboards/admin/networks/subnets/tables.py
  3. +1
    -1
      openstack_dashboard/dashboards/admin/networks/subnets/tests.py
  4. +3
    -3
      openstack_dashboard/dashboards/admin/networks/tables.py
  5. +8
    -8
      openstack_dashboard/dashboards/admin/networks/tests.py
  6. +2
    -2
      openstack_dashboard/dashboards/project/floating_ips/forms.py
  7. +2
    -2
      openstack_dashboard/dashboards/project/floating_ips/tables.py
  8. +5
    -5
      openstack_dashboard/dashboards/project/floating_ips/templates/floating_ips/_allocate.html
  9. +6
    -9
      openstack_dashboard/dashboards/project/floating_ips/tests.py
  10. +1
    -1
      openstack_dashboard/dashboards/project/floating_ips/views.py
  11. +4
    -4
      openstack_dashboard/dashboards/project/network_topology/tests.py
  12. +2
    -2
      openstack_dashboard/dashboards/project/network_topology/utils.py
  13. +3
    -3
      openstack_dashboard/dashboards/project/networks/ports/tables.py
  14. +3
    -3
      openstack_dashboard/dashboards/project/networks/subnets/tables.py
  15. +6
    -6
      openstack_dashboard/dashboards/project/networks/tables.py
  16. +27
    -27
      openstack_dashboard/dashboards/project/networks/tests.py
  17. +3
    -3
      openstack_dashboard/dashboards/project/routers/tables.py
  18. +11
    -11
      openstack_dashboard/dashboards/project/routers/tests.py
  19. +2
    -2
      openstack_dashboard/dashboards/project/security_groups/tables.py
  20. +9
    -9
      openstack_dashboard/dashboards/project/security_groups/tests.py
  21. +7
    -5
      openstack_dashboard/test/test_data/neutron_data.py
  22. +18
    -20
      openstack_dashboard/test/unit/usage/test_quotas.py
  23. +32
    -100
      openstack_dashboard/usage/quotas.py

+ 2
- 2
openstack_dashboard/dashboards/admin/networks/ports/tables.py View File

@@ -38,8 +38,8 @@ class CreatePort(project_tables.CreatePort):
network = self.table._get_network()
tenant_id = network.tenant_id
usages = quotas.tenant_quota_usages(
request, tenant_id=tenant_id, targets=('ports', ))
if usages.get('ports', {}).get('available', 1) <= 0:
request, tenant_id=tenant_id, targets=('port', ))
if usages.get('port', {}).get('available', 1) <= 0:
if "disabled" not in self.classes:
self.classes = [c for c in self.classes] + ["disabled"]
self.verbose_name = _("Create Port (Quota exceeded)")

+ 3
- 3
openstack_dashboard/dashboards/admin/networks/subnets/tables.py View File

@@ -80,11 +80,11 @@ class CreateSubnet(proj_tables.SubnetPolicyTargetMixin, tables.LinkAction):
def allowed(self, request, datum=None):
network = self.table._get_network()
usages = quotas.tenant_quota_usages(
request, tenant_id=network.tenant_id, targets=('subnets', ))
request, tenant_id=network.tenant_id, targets=('subnet', ))

# when Settings.OPENSTACK_NEUTRON_NETWORK['enable_quotas'] = False
# usages["subnets'] is empty
if usages.get('subnets', {}).get('available', 1) <= 0:
# usages["subnet'] is empty
if usages.get('subnet', {}).get('available', 1) <= 0:
if 'disabled' not in self.classes:
self.classes = [c for c in self.classes] + ['disabled']
self.verbose_name = _('Create Subnet (Quota exceeded)')

+ 1
- 1
openstack_dashboard/dashboards/admin/networks/subnets/tests.py View File

@@ -436,7 +436,7 @@ class NetworkSubnetTests(test.BaseAdminViewTests):
.MultipleTimes().AndReturn(True)
quotas.tenant_quota_usages(
IsA(http.HttpRequest), tenant_id=network.tenant_id,
targets=('subnets',)).MultipleTimes().AndReturn(quota_data)
targets=('subnet',)).MultipleTimes().AndReturn(quota_data)
self.mox.ReplayAll()
from django.utils.http import urlunquote
url = urlunquote(reverse('horizon:admin:networks:subnets_tab',

+ 3
- 3
openstack_dashboard/dashboards/admin/networks/tables.py View File

@@ -85,11 +85,11 @@ class CreateSubnet(project_tables.CreateSubnet):

def allowed(self, request, datum=None):
usages = quotas.tenant_quota_usages(
request, tenant_id=datum.tenant_id, targets=('subnets', ))
request, tenant_id=datum.tenant_id, targets=('subnet', ))

# when Settings.OPENSTACK_NEUTRON_NETWORK['enable_quotas'] = False
# usages["subnets'] is empty
if usages.get('subnets', {}).get('available', 1) <= 0:
# usages["subnet'] is empty
if usages.get('subnet', {}).get('available', 1) <= 0:
if 'disabled' not in self.classes:
self.classes = [c for c in self.classes] + ['disabled']
self.verbose_name = _('Create Subnet (Quota exceeded)')

+ 8
- 8
openstack_dashboard/dashboards/admin/networks/tests.py View File

@@ -49,7 +49,7 @@ class NetworkTests(test.BaseAdminViewTests):
for network in self.networks.list():
usage.quotas.tenant_quota_usages(
IsA(http.HttpRequest), tenant_id=network.tenant_id,
targets=('subnets', )).AndReturn(quota_data)
targets=('subnet', )).AndReturn(quota_data)
api.neutron.list_dhcp_agent_hosting_networks(IsA(http.HttpRequest),
network.id)\
.AndReturn(self.agents.list())
@@ -131,7 +131,7 @@ class NetworkTests(test.BaseAdminViewTests):
'dhcp_agent_scheduler').AndReturn(True)
usage.quotas.tenant_quota_usages(
IsA(http.HttpRequest), tenant_id=network.tenant_id,
targets=('subnets',)).MultipleTimes().AndReturn(quota_data)
targets=('subnet',)).MultipleTimes().AndReturn(quota_data)
self.mox.ReplayAll()
url = urlunquote(reverse('horizon:admin:networks:detail',
args=[network.id]))
@@ -172,7 +172,7 @@ class NetworkTests(test.BaseAdminViewTests):
'dhcp_agent_scheduler').AndReturn(True)
usage.quotas.tenant_quota_usages(
IsA(http.HttpRequest), tenant_id=network.tenant_id,
targets=('subnets',)).MultipleTimes().AndReturn(quota_data)
targets=('subnet',)).MultipleTimes().AndReturn(quota_data)
self.mox.ReplayAll()
url = urlunquote(reverse('horizon:admin:networks:subnets_tab',
args=[network.id]))
@@ -197,7 +197,7 @@ class NetworkTests(test.BaseAdminViewTests):
quota_data = self.neutron_quota_usages.first()
usage.quotas.tenant_quota_usages(
IsA(http.HttpRequest), tenant_id=network.tenant_id,
targets=('ports',)).MultipleTimes().AndReturn(quota_data)
targets=('port',)).MultipleTimes().AndReturn(quota_data)
api.neutron.is_extension_supported(
IsA(http.HttpRequest),
'network-ip-availability').AndReturn(True)
@@ -212,7 +212,7 @@ class NetworkTests(test.BaseAdminViewTests):
'dhcp_agent_scheduler').AndReturn(True)
usage.quotas.tenant_quota_usages(
IsA(http.HttpRequest), tenant_id=network.tenant_id,
targets=('subnets',)).MultipleTimes().AndReturn(quota_data)
targets=('subnet',)).MultipleTimes().AndReturn(quota_data)

self.mox.ReplayAll()
url = reverse('horizon:admin:networks:ports_tab',
@@ -255,7 +255,7 @@ class NetworkTests(test.BaseAdminViewTests):
'dhcp_agent_scheduler').AndReturn(True)
usage.quotas.tenant_quota_usages(
IsA(http.HttpRequest), tenant_id=network.tenant_id,
targets=('subnets',)).MultipleTimes().AndReturn(quota_data)
targets=('subnet',)).MultipleTimes().AndReturn(quota_data)
self.mox.ReplayAll()
url = reverse('horizon:admin:networks:agents_tab', args=[network.id])
res = self.client.get(urlunquote(url))
@@ -359,7 +359,7 @@ class NetworkTests(test.BaseAdminViewTests):
'dhcp_agent_scheduler').AndReturn(True)
usage.quotas.tenant_quota_usages(
IsA(http.HttpRequest), tenant_id=network.tenant_id,
targets=('subnets',)).MultipleTimes().AndReturn(quota_data)
targets=('subnet',)).MultipleTimes().AndReturn(quota_data)
self.mox.ReplayAll()
url = urlunquote(reverse('horizon:admin:networks:subnets_tab',
args=[network.id]))
@@ -418,7 +418,7 @@ class NetworkTests(test.BaseAdminViewTests):
.AndReturn(True)
usage.quotas.tenant_quota_usages(
IsA(http.HttpRequest), tenant_id=network.tenant_id,
targets=('subnets',)).MultipleTimes().AndReturn(quota_data)
targets=('subnet',)).MultipleTimes().AndReturn(quota_data)
self.mox.ReplayAll()
url = urlunquote(reverse('horizon:admin:networks:subnets_tab',
args=[network.id]))

+ 2
- 2
openstack_dashboard/dashboards/project/floating_ips/forms.py View File

@@ -39,8 +39,8 @@ class FloatingIpAllocate(forms.SelfHandlingForm):
try:
# Prevent allocating more IP than the quota allows
usages = quotas.tenant_quota_usages(request,
targets=('floating_ips', ))
if usages['floating_ips']['available'] <= 0:
targets=('floatingip', ))
if usages['floatingip']['available'] <= 0:
error_message = _('You are already using all of your available'
' floating IPs.')
self.api_error(error_message)

+ 2
- 2
openstack_dashboard/dashboards/project/floating_ips/tables.py View File

@@ -48,8 +48,8 @@ class AllocateIP(tables.LinkAction):

def allowed(self, request, fip=None):
usages = quotas.tenant_quota_usages(request,
targets=('floating_ips', ))
if usages['floating_ips']['available'] <= 0:
targets=('floatingip', ))
if usages['floatingip']['available'] <= 0:
if "disabled" not in self.classes:
self.classes = [c for c in self.classes] + ['disabled']
self.verbose_name = string_concat(self.verbose_name, ' ',

+ 5
- 5
openstack_dashboard/dashboards/project/floating_ips/templates/floating_ips/_allocate.html View File

@@ -12,15 +12,15 @@
<strong>{% trans "Floating IP" %}</strong>
</div>
<span class="pull-right">
{% blocktrans with used=usages.floating_ips.used quota=usages.floating_ips.quota|quotainf %}{{ used }} of {{ quota }} Used{% endblocktrans %}
{% blocktrans with used=usages.floatingip.used quota=usages.floatingip.quota|quotainf %}{{ used }} of {{ quota }} Used{% endblocktrans %}
</span>
</div>
<div id="floating_ip_progress"
class="quota_bar"
data-quota-used="{{ usages.floating_ips.used }}"
data-quota-limit="{{ usages.floating_ips.quota }}">
{% widthratio usages.floating_ips.used usages.floating_ips.quota 100 as ip_percent %}
{% widthratio 100 usages.floating_ips.quota 1 as single_step %}
data-quota-used="{{ usages.floatingip.used }}"
data-quota-limit="{{ usages.floatingip.quota }}">
{% widthratio usages.floatingip.used usages.floatingip.quota 100 as ip_percent %}
{% widthratio 100 usages.floatingip.quota 1 as single_step %}
{% bs_progress_bar ip_percent single_step %}
</div>
</div>

+ 6
- 9
openstack_dashboard/dashboards/project/floating_ips/tests.py View File

@@ -246,8 +246,7 @@ class FloatingIpViewTests(test.TestCase):
def test_allocate_button_attributes(self):
floating_ips = self.floating_ips.list()
floating_pools = self.pools.list()
quota_data = self.quota_usages.first()
quota_data['floating_ips']['available'] = 10
quota_data = self.neutron_quota_usages.first()

api.neutron.tenant_floating_ip_list(
IsA(http.HttpRequest)) \
@@ -259,7 +258,7 @@ class FloatingIpViewTests(test.TestCase):
IsA(http.HttpRequest), detailed=False) \
.AndReturn([self.servers.list(), False])
quotas.tenant_quota_usages(
IsA(http.HttpRequest), targets=('floating_ips', )).MultipleTimes() \
IsA(http.HttpRequest), targets=('floatingip', )).MultipleTimes() \
.AndReturn(quota_data)

self.mox.ReplayAll()
@@ -284,8 +283,8 @@ class FloatingIpViewTests(test.TestCase):
def test_allocate_button_disabled_when_quota_exceeded(self):
floating_ips = self.floating_ips.list()
floating_pools = self.pools.list()
quota_data = self.quota_usages.first()
quota_data['floating_ips']['available'] = 0
quota_data = self.neutron_quota_usages.first()
quota_data['floatingip']['available'] = 0

api.neutron.tenant_floating_ip_list(
IsA(http.HttpRequest)) \
@@ -297,7 +296,7 @@ class FloatingIpViewTests(test.TestCase):
IsA(http.HttpRequest), detailed=False) \
.AndReturn([self.servers.list(), False])
quotas.tenant_quota_usages(
IsA(http.HttpRequest), targets=('floating_ips', )).MultipleTimes() \
IsA(http.HttpRequest), targets=('floatingip', )).MultipleTimes() \
.AndReturn(quota_data)

self.mox.ReplayAll()
@@ -337,8 +336,6 @@ class FloatingIpViewTests(test.TestCase):
'quota_details').AndReturn(False)
api.neutron.tenant_quota_get(IsA(http.HttpRequest), self.tenant.id) \
.AndReturn(self.neutron_quotas.first())
api.neutron.floating_ip_supported(IsA(http.HttpRequest)) \
.AndReturn(True)
api.neutron.tenant_floating_ip_list(IsA(http.HttpRequest)) \
.MultipleTimes().AndReturn(self.floating_ips.list())
api.neutron.floating_ip_pools_list(IsA(http.HttpRequest)) \
@@ -347,5 +344,5 @@ class FloatingIpViewTests(test.TestCase):

url = reverse('%s:allocate' % NAMESPACE)
res = self.client.get(url)
self.assertEqual(res.context['usages']['floating_ips']['quota'],
self.assertEqual(res.context['usages']['floatingip']['quota'],
self.neutron_quotas.first().get('floatingip').limit)

+ 1
- 1
openstack_dashboard/dashboards/project/floating_ips/views.py View File

@@ -62,7 +62,7 @@ class AllocateView(forms.ModalFormView):
context = super(AllocateView, self).get_context_data(**kwargs)
try:
context['usages'] = quotas.tenant_quota_usages(
self.request, targets=('floating_ips', ))
self.request, targets=('floatingip', ))
except Exception:
exceptions.handle(self.request)
return context

+ 4
- 4
openstack_dashboard/dashboards/project/network_topology/tests.py View File

@@ -198,18 +198,18 @@ class NetworkTopologyCreateTests(test.TestCase):
self, expected_string, networks_quota=10,
routers_quota=10, instances_quota=10):
quota_data = self.quota_usages.first()
quota_data['networks']['available'] = networks_quota
quota_data['routers']['available'] = routers_quota
quota_data['network']['available'] = networks_quota
quota_data['router']['available'] = routers_quota
quota_data['instances']['available'] = instances_quota

quotas.tenant_quota_usages(
IsA(http.HttpRequest), targets=('instances', )
).MultipleTimes().AndReturn(quota_data)
quotas.tenant_quota_usages(
IsA(http.HttpRequest), targets=('networks', )
IsA(http.HttpRequest), targets=('network', )
).MultipleTimes().AndReturn(quota_data)
quotas.tenant_quota_usages(
IsA(http.HttpRequest), targets=('routers', )
IsA(http.HttpRequest), targets=('router', )
).MultipleTimes().AndReturn(quota_data)

self.mox.ReplayAll()

+ 2
- 2
openstack_dashboard/dashboards/project/network_topology/utils.py View File

@@ -35,11 +35,11 @@ def get_context(request, context=None):
context['instance_quota_exceeded'] = _quota_exceeded(request, 'instances')
context['create_network_allowed'] = policy.check(
(("network", "create_network"),), request)
context['network_quota_exceeded'] = _quota_exceeded(request, 'networks')
context['network_quota_exceeded'] = _quota_exceeded(request, 'network')
context['create_router_allowed'] = (
network_config.get('enable_router', True) and
policy.check((("network", "create_router"),), request))
context['router_quota_exceeded'] = _quota_exceeded(request, 'routers')
context['router_quota_exceeded'] = _quota_exceeded(request, 'router')
context['console_type'] = getattr(settings, 'CONSOLE_TYPE', 'AUTO')
context['show_ng_launch'] = (
base.is_service_enabled(request, 'compute') and

+ 3
- 3
openstack_dashboard/dashboards/project/networks/ports/tables.py View File

@@ -88,10 +88,10 @@ class CreatePort(tables.LinkAction):
return reverse(self.url, args=(network_id,))

def allowed(self, request, datum=None):
usages = quotas.tenant_quota_usages(request, targets=('ports', ))
usages = quotas.tenant_quota_usages(request, targets=('port', ))
# when Settings.OPENSTACK_NEUTRON_NETWORK['enable_quotas'] = False
# usages["ports"] is empty
if usages.get('ports', {}).get('available', 1) <= 0:
# usages["port"] is empty
if usages.get('port', {}).get('available', 1) <= 0:
if "disabled" not in self.classes:
self.classes = [c for c in self.classes] + ["disabled"]
self.verbose_name = _("Create Port (Quota exceeded)")

+ 3
- 3
openstack_dashboard/dashboards/project/networks/subnets/tables.py View File

@@ -99,11 +99,11 @@ class CreateSubnet(SubnetPolicyTargetMixin, tables.LinkAction):
return reverse(self.url, args=(network_id,))

def allowed(self, request, datum=None):
usages = quotas.tenant_quota_usages(request, targets=('subnets', ))
usages = quotas.tenant_quota_usages(request, targets=('subnet', ))

# when Settings.OPENSTACK_NEUTRON_NETWORK['enable_quotas'] = False
# usages["subnets'] is empty
if usages.get('subnets', {}).get('available', 1) <= 0:
# usages["subnet'] is empty
if usages.get('subnet', {}).get('available', 1) <= 0:
if 'disabled' not in self.classes:
self.classes = [c for c in self.classes] + ['disabled']
self.verbose_name = _('Create Subnet (Quota exceeded)')

+ 6
- 6
openstack_dashboard/dashboards/project/networks/tables.py View File

@@ -92,10 +92,10 @@ class CreateNetwork(tables.LinkAction):
policy_rules = (("network", "create_network"),)

def allowed(self, request, datum=None):
usages = quotas.tenant_quota_usages(request, targets=('networks', ))
usages = quotas.tenant_quota_usages(request, targets=('network', ))
# when Settings.OPENSTACK_NEUTRON_NETWORK['enable_quotas'] = False
# usages["networks"] is empty
if usages.get('networks', {}).get('available', 1) <= 0:
# usages["network"] is empty
if usages.get('network', {}).get('available', 1) <= 0:
if "disabled" not in self.classes:
self.classes = [c for c in self.classes] + ["disabled"]
self.verbose_name = _("Create Network (Quota exceeded)")
@@ -127,10 +127,10 @@ class CreateSubnet(subnet_tables.SubnetPolicyTargetMixin, tables.LinkAction):
("network:project_id", "tenant_id"),)

def allowed(self, request, datum=None):
usages = quotas.tenant_quota_usages(request, targets=('subnets', ))
usages = quotas.tenant_quota_usages(request, targets=('subnet', ))
# when Settings.OPENSTACK_NEUTRON_NETWORK['enable_quotas'] = False
# usages["subnets'] is empty
if usages.get('subnets', {}).get('available', 1) <= 0:
# usages["subnet'] is empty
if usages.get('subnet', {}).get('available', 1) <= 0:
if 'disabled' not in self.classes:
self.classes = [c for c in self.classes] + ['disabled']
self.verbose_name = _('Create Subnet (Quota exceeded)')

+ 27
- 27
openstack_dashboard/dashboards/project/networks/tests.py View File

@@ -127,15 +127,15 @@ class NetworkTests(test.TestCase, NetworkStubMixin):
'is_extension_supported'),
quotas: ('tenant_quota_usages',)})
def test_index(self):
quota_data = self.quota_usages.first()
quota_data['networks']['available'] = 5
quota_data['subnets']['available'] = 5
quota_data = self.neutron_quota_usages.first()
quota_data['network']['available'] = 5
quota_data['subnet']['available'] = 5
self._stub_net_list()
quotas.tenant_quota_usages(
IsA(http.HttpRequest), targets=('networks', )) \
IsA(http.HttpRequest), targets=('network', )) \
.MultipleTimes().AndReturn(quota_data)
quotas.tenant_quota_usages(
IsA(http.HttpRequest), targets=('subnets', )) \
IsA(http.HttpRequest), targets=('subnet', )) \
.MultipleTimes().AndReturn(quota_data)
api.neutron.is_extension_supported(
IsA(http.HttpRequest), 'network_availability_zone')\
@@ -158,7 +158,7 @@ class NetworkTests(test.TestCase, NetworkStubMixin):
tenant_id=self.tenant.id,
shared=False).MultipleTimes().AndRaise(self.exceptions.neutron)
quotas.tenant_quota_usages(
IsA(http.HttpRequest), targets=('networks', )) \
IsA(http.HttpRequest), targets=('network', )) \
.MultipleTimes().AndReturn(quota_data)
api.neutron.is_extension_supported(
IsA(http.HttpRequest), 'network_availability_zone')\
@@ -200,7 +200,7 @@ class NetworkTests(test.TestCase, NetworkStubMixin):
.AndReturn(mac_learning)

quotas.tenant_quota_usages(
IsA(http.HttpRequest), targets=('subnets', )) \
IsA(http.HttpRequest), targets=('subnet', )) \
.MultipleTimes().AndReturn(quota_data)
api.neutron.is_extension_supported(
IsA(http.HttpRequest), 'network_availability_zone')\
@@ -228,7 +228,7 @@ class NetworkTests(test.TestCase, NetworkStubMixin):
'mac-learning')\
.AndReturn(mac_learning)
quotas.tenant_quota_usages(
IsA(http.HttpRequest), targets=('subnets', )) \
IsA(http.HttpRequest), targets=('subnet', )) \
.MultipleTimes().AndReturn(quota_data)
api.neutron.is_extension_supported(
IsA(http.HttpRequest), 'network_availability_zone')\
@@ -291,8 +291,8 @@ class NetworkTests(test.TestCase, NetworkStubMixin):
def _test_subnets_tab_subnet_exception(self, mac_learning=False):
network_id = self.networks.first().id
quota_data = self.neutron_quota_usages.first()
quota_data['networks']['available'] = 5
quota_data['subnets']['available'] = 5
quota_data['network']['available'] = 5
quota_data['subnet']['available'] = 5
api.neutron.network_get(IsA(http.HttpRequest), network_id).\
MultipleTimes().AndReturn(self.networks.first())
api.neutron.subnet_list(IsA(http.HttpRequest), network_id=network_id).\
@@ -302,7 +302,7 @@ class NetworkTests(test.TestCase, NetworkStubMixin):
'mac-learning')\
.AndReturn(mac_learning)
quotas.tenant_quota_usages(
IsA(http.HttpRequest), targets=('subnets', )) \
IsA(http.HttpRequest), targets=('subnet', )) \
.MultipleTimes().AndReturn(quota_data)
api.neutron.is_extension_supported(
IsA(http.HttpRequest), 'network_availability_zone')\
@@ -336,7 +336,7 @@ class NetworkTests(test.TestCase, NetworkStubMixin):
def _test_subnets_tab_port_exception(self, mac_learning=False):
network_id = self.networks.first().id
quota_data = self.neutron_quota_usages.first()
quota_data['subnets']['available'] = 5
quota_data['subnet']['available'] = 5
api.neutron.network_get(IsA(http.HttpRequest), network_id).\
AndReturn(self.networks.first())
api.neutron.subnet_list(IsA(http.HttpRequest), network_id=network_id).\
@@ -345,7 +345,7 @@ class NetworkTests(test.TestCase, NetworkStubMixin):
'mac-learning')\
.AndReturn(mac_learning)
quotas.tenant_quota_usages(
IsA(http.HttpRequest), targets=('subnets', )) \
IsA(http.HttpRequest), targets=('subnet', )) \
.MultipleTimes().AndReturn(quota_data)
api.neutron.is_extension_supported(
IsA(http.HttpRequest), 'network_availability_zone')\
@@ -1096,15 +1096,15 @@ class NetworkViewTests(test.TestCase, NetworkStubMixin):
# these keys are empty dicts, its disabled
quota_data = self.neutron_quota_usages.first()

quota_data['networks'].pop('available')
quota_data['subnets'].pop('available')
quota_data['network'].pop('available')
quota_data['subnet'].pop('available')

self._stub_net_list()
quotas.tenant_quota_usages(
IsA(http.HttpRequest), targets=('networks', )) \
IsA(http.HttpRequest), targets=('network', )) \
.MultipleTimes().AndReturn(quota_data)
quotas.tenant_quota_usages(
IsA(http.HttpRequest), targets=('subnets', )) \
IsA(http.HttpRequest), targets=('subnet', )) \
.MultipleTimes().AndReturn(quota_data)
api.neutron.is_extension_supported(
IsA(http.HttpRequest), 'network_availability_zone')\
@@ -1128,15 +1128,15 @@ class NetworkViewTests(test.TestCase, NetworkStubMixin):

quota_data = self.neutron_quota_usages.first()

quota_data['networks']['available'] = network_quota
quota_data['subnets']['available'] = subnet_quota
quota_data['network']['available'] = network_quota
quota_data['subnet']['available'] = subnet_quota

self._stub_net_list()
quotas.tenant_quota_usages(
IsA(http.HttpRequest), targets=('networks', )) \
IsA(http.HttpRequest), targets=('network', )) \
.MultipleTimes().AndReturn(quota_data)
quotas.tenant_quota_usages(
IsA(http.HttpRequest), targets=('subnets', )) \
IsA(http.HttpRequest), targets=('subnet', )) \
.MultipleTimes().AndReturn(quota_data)
api.neutron.is_extension_supported(
IsA(http.HttpRequest), 'network_availability_zone')\
@@ -1221,7 +1221,7 @@ class NetworkViewTests(test.TestCase, NetworkStubMixin):
IsA(http.HttpRequest), 'mac-learning')\
.AndReturn(False)
quotas.tenant_quota_usages(
IsA(http.HttpRequest), targets=('subnets', )) \
IsA(http.HttpRequest), targets=('subnet', )) \
.MultipleTimes().AndReturn(quota_data)
api.neutron.is_extension_supported(
IsA(http.HttpRequest), 'network_availability_zone')\
@@ -1242,7 +1242,7 @@ class NetworkViewTests(test.TestCase, NetworkStubMixin):

def test_subnet_create_button_disabled_when_quota_exceeded_detail(self):
quota_data = self.neutron_quota_usages.first()
quota_data['subnets']['available'] = 0
quota_data['subnet']['available'] = 0
create_action = self._test_subnet_create_button(quota_data)
self.assertIn('disabled', create_action.classes,
'The create button should be disabled')
@@ -1300,10 +1300,10 @@ class NetworkViewTests(test.TestCase, NetworkStubMixin):
IsA(http.HttpRequest), 'mac-learning') \
.AndReturn(False)
quotas.tenant_quota_usages(
IsA(http.HttpRequest), targets=('subnets', )) \
IsA(http.HttpRequest), targets=('subnet', )) \
.MultipleTimes().AndReturn(quota_data)
quotas.tenant_quota_usages(
IsA(http.HttpRequest), targets=('ports',)) \
IsA(http.HttpRequest), targets=('port',)) \
.MultipleTimes().AndReturn(quota_data)
api.neutron.is_extension_supported(
IsA(http.HttpRequest), 'network_availability_zone')\
@@ -1323,7 +1323,7 @@ class NetworkViewTests(test.TestCase, NetworkStubMixin):

def test_port_create_button_disabled_when_quota_exceeded(self):
quota_data = self.neutron_quota_usages.first()
quota_data['ports']['available'] = 0
quota_data['port']['available'] = 0
create_action = self._test_port_create_button(quota_data)
self.assertIn('disabled', create_action.classes,
'The create button should be disabled')
@@ -1338,7 +1338,7 @@ class NetworkViewTests(test.TestCase, NetworkStubMixin):

def test_create_port_button_attributes(self):
quota_data = self.neutron_quota_usages.first()
quota_data['ports']['available'] = 1
quota_data['port']['available'] = 1
create_action = self._test_port_create_button(quota_data)

self.assertEqual(set(['ajax-modal']), set(create_action.classes))

+ 3
- 3
openstack_dashboard/dashboards/project/routers/tables.py View File

@@ -96,10 +96,10 @@ class CreateRouter(tables.LinkAction):
policy_rules = (("network", "create_router"),)

def allowed(self, request, datum=None):
usages = quotas.tenant_quota_usages(request, targets=('routers', ))
usages = quotas.tenant_quota_usages(request, targets=('router', ))
# when Settings.OPENSTACK_NEUTRON_NETWORK['enable_quotas'] = False
# usages['routers'] is empty
if usages.get('routers', {}).get('available', 1) <= 0:
# usages['router'] is empty
if usages.get('router', {}).get('available', 1) <= 0:
if "disabled" not in self.classes:
self.classes = [c for c in self.classes] + ["disabled"]
self.verbose_name = _("Create Router (Quota exceeded)")

+ 11
- 11
openstack_dashboard/dashboards/project/routers/tests.py View File

@@ -102,7 +102,7 @@ class RouterTests(RouterMixin, test.TestCase):
IsA(http.HttpRequest),
tenant_id=self.tenant.id).AndReturn(self.routers.list())
quotas.tenant_quota_usages(
IsA(http.HttpRequest), targets=('routers', )) \
IsA(http.HttpRequest), targets=('router', )) \
.MultipleTimes().AndReturn(quota_data)
api.neutron.is_extension_supported(IsA(http.HttpRequest),
"router_availability_zone")\
@@ -126,7 +126,7 @@ class RouterTests(RouterMixin, test.TestCase):
tenant_id=self.tenant.id).MultipleTimes().AndRaise(
self.exceptions.neutron)
quotas.tenant_quota_usages(
IsA(http.HttpRequest), targets=('routers', )) \
IsA(http.HttpRequest), targets=('router', )) \
.MultipleTimes().AndReturn(quota_data)
api.neutron.is_extension_supported(IsA(http.HttpRequest),
"router_availability_zone")\
@@ -150,7 +150,7 @@ class RouterTests(RouterMixin, test.TestCase):
IsA(http.HttpRequest),
tenant_id=self.tenant.id).MultipleTimes().AndReturn([router])
quotas.tenant_quota_usages(
IsA(http.HttpRequest), targets=('routers', )) \
IsA(http.HttpRequest), targets=('router', )) \
.MultipleTimes().AndReturn(quota_data)
api.neutron.is_extension_supported(IsA(http.HttpRequest),
"router_availability_zone")\
@@ -198,7 +198,7 @@ class RouterTests(RouterMixin, test.TestCase):
IsA(http.HttpRequest),
tenant_id=self.tenant.id).AndReturn(self.routers.list())
quotas.tenant_quota_usages(
IsA(http.HttpRequest), targets=('routers', )) \
IsA(http.HttpRequest), targets=('router', )) \
.MultipleTimes().AndReturn(quota_data)
api.neutron.is_extension_supported(IsA(http.HttpRequest),
"router_availability_zone")\
@@ -240,7 +240,7 @@ class RouterTests(RouterMixin, test.TestCase):
IsA(http.HttpRequest),
tenant_id=self.tenant.id).AndReturn(self.routers.list())
quotas.tenant_quota_usages(
IsA(http.HttpRequest), targets=('routers', )) \
IsA(http.HttpRequest), targets=('router', )) \
.MultipleTimes().AndReturn(quota_data)
api.neutron.is_extension_supported(IsA(http.HttpRequest),
"router_availability_zone")\
@@ -928,12 +928,12 @@ class RouterViewTests(RouterMixin, test.TestCase):
quotas: ('tenant_quota_usages',)})
def test_create_button_disabled_when_quota_exceeded(self):
quota_data = self.neutron_quota_usages.first()
quota_data['routers']['available'] = 0
quota_data['router']['available'] = 0
api.neutron.router_list(
IsA(http.HttpRequest),
tenant_id=self.tenant.id).AndReturn(self.routers.list())
quotas.tenant_quota_usages(
IsA(http.HttpRequest), targets=('routers', )) \
IsA(http.HttpRequest), targets=('router', )) \
.MultipleTimes().AndReturn(quota_data)
api.neutron.is_extension_supported(IsA(http.HttpRequest),
"router_availability_zone")\
@@ -959,12 +959,12 @@ class RouterViewTests(RouterMixin, test.TestCase):
quotas: ('tenant_quota_usages',)})
def test_create_button_shown_when_quota_disabled(self):
quota_data = self.neutron_quota_usages.first()
quota_data['routers'].pop('available')
quota_data['router'].pop('available')
api.neutron.router_list(
IsA(http.HttpRequest),
tenant_id=self.tenant.id).AndReturn(self.routers.list())
quotas.tenant_quota_usages(
IsA(http.HttpRequest), targets=('routers', )) \
IsA(http.HttpRequest), targets=('router', )) \
.MultipleTimes().AndReturn(quota_data)
api.neutron.is_extension_supported(IsA(http.HttpRequest),
"router_availability_zone")\
@@ -990,12 +990,12 @@ class RouterViewTests(RouterMixin, test.TestCase):
quotas: ('tenant_quota_usages',)})
def test_create_button_attributes(self):
quota_data = self.neutron_quota_usages.first()
quota_data['routers']['available'] = 10
quota_data['router']['available'] = 10
api.neutron.router_list(
IsA(http.HttpRequest),
tenant_id=self.tenant.id).AndReturn(self.routers.list())
quotas.tenant_quota_usages(
IsA(http.HttpRequest), targets=('routers', )) \
IsA(http.HttpRequest), targets=('router', )) \
.MultipleTimes().AndReturn(quota_data)
api.neutron.is_extension_supported(IsA(http.HttpRequest),
"router_availability_zone")\

+ 2
- 2
openstack_dashboard/dashboards/project/security_groups/tables.py View File

@@ -64,8 +64,8 @@ class CreateGroup(tables.LinkAction):

def allowed(self, request, security_group=None):
usages = quotas.tenant_quota_usages(request,
targets=('security_groups', ))
if usages['security_groups'].get('available', 1) <= 0:
targets=('security_group', ))
if usages['security_group'].get('available', 1) <= 0:
if "disabled" not in self.classes:
self.classes = [c for c in self.classes] + ["disabled"]
self.verbose_name = _("Create Security Group (Quota exceeded)")

+ 9
- 9
openstack_dashboard/dashboards/project/security_groups/tests.py View File

@@ -68,14 +68,14 @@ class SecurityGroupsViewTests(test.TestCase):
quotas: ('tenant_quota_usages',)})
def test_index(self):
sec_groups = self.security_groups.list()
quota_data = self.quota_usages.first()
quota_data['security_groups']['available'] = 10
quota_data = self.neutron_quota_usages.first()
quota_data['security_group']['available'] = 10

api.neutron.security_group_list(IsA(http.HttpRequest)) \
.AndReturn(sec_groups)
quotas.tenant_quota_usages(
IsA(http.HttpRequest),
targets=('security_groups', )).MultipleTimes() \
targets=('security_group', )).MultipleTimes() \
.AndReturn(quota_data)

self.mox.ReplayAll()
@@ -101,15 +101,15 @@ class SecurityGroupsViewTests(test.TestCase):
quotas: ('tenant_quota_usages',)})
def test_create_button_attributes(self):
sec_groups = self.security_groups.list()
quota_data = self.quota_usages.first()
quota_data['security_groups']['available'] = 10
quota_data = self.neutron_quota_usages.first()
quota_data['security_group']['available'] = 10

api.neutron.security_group_list(
IsA(http.HttpRequest)) \
.AndReturn(sec_groups)
quotas.tenant_quota_usages(
IsA(http.HttpRequest),
targets=('security_groups', )).MultipleTimes() \
targets=('security_group', )).MultipleTimes() \
.AndReturn(quota_data)

self.mox.ReplayAll()
@@ -135,15 +135,15 @@ class SecurityGroupsViewTests(test.TestCase):
def _test_create_button_disabled_when_quota_exceeded(self,
network_enabled):
sec_groups = self.security_groups.list()
quota_data = self.quota_usages.first()
quota_data['security_groups']['available'] = 0
quota_data = self.neutron_quota_usages.first()
quota_data['security_group']['available'] = 0

api.neutron.security_group_list(
IsA(http.HttpRequest)) \
.AndReturn(sec_groups)
quotas.tenant_quota_usages(
IsA(http.HttpRequest),
targets=('security_groups', )).MultipleTimes() \
targets=('security_group', )).MultipleTimes() \
.AndReturn(quota_data)

self.mox.ReplayAll()

+ 7
- 5
openstack_dashboard/test/test_data/neutron_data.py View File

@@ -618,11 +618,13 @@ def data(TEST):
TEST.neutron_quotas.add(base.QuotaSet(quota_data))

# Quota Usages
quota_usage_data = {'networks': {'used': 0, 'quota': 5},
'subnets': {'used': 0, 'quota': 5},
'ports': {'used': 0, 'quota': 5},
'routers': {'used': 0, 'quota': 5},
}
quota_usage_data = {
'network': {'used': 0, 'quota': 5},
'subnet': {'used': 0, 'quota': 5},
'port': {'used': 0, 'quota': 5},
'router': {'used': 0, 'quota': 5},
'floatingip': {'used': 0, 'quota': 10},
}
quota_usage = usage_quotas.QuotaUsage()
for k, v in quota_usage_data.items():
quota_usage.add_quota(base.Quota(k, v['quota']))

+ 18
- 20
openstack_dashboard/test/unit/usage/test_quotas.py View File

@@ -437,15 +437,15 @@ class QuotaTests(test.APITestCase):

def test_tenant_quota_usages_neutron_with_target_network_resources(self):
self._test_tenant_quota_usages_neutron_with_target(
targets=('networks', 'subnets', 'routers', ))
targets=('network', 'subnet', 'router', ))

def test_tenant_quota_usages_neutron_with_target_security_groups(self):
self._test_tenant_quota_usages_neutron_with_target(
targets=('security_groups', ))
targets=('security_group', ))

def test_tenant_quota_usages_neutron_with_target_floating_ips(self):
self._test_tenant_quota_usages_neutron_with_target(
targets=('floating_ips', ))
targets=('floatingip', ))

@test.create_stubs({api.base: ('is_service_enabled',),
api.neutron: ('floating_ip_supported',
@@ -476,24 +476,22 @@ class QuotaTests(test.APITestCase):
'quota_details').AndReturn(False)
api.neutron.tenant_quota_get(IsA(http.HttpRequest), '1') \
.AndReturn(self.neutron_quotas.first())
if 'networks' in targets:
if 'network' in targets:
api.neutron.network_list(IsA(http.HttpRequest),
tenant_id=self.request.user.tenant_id) \
.AndReturn(self.networks.list())
if 'subnets' in targets:
if 'subnet' in targets:
api.neutron.subnet_list(IsA(http.HttpRequest),
tenant_id=self.request.user.tenant_id) \
.AndReturn(self.subnets.list())
if 'routers' in targets:
if 'router' in targets:
api.neutron.router_list(IsA(http.HttpRequest),
tenant_id=self.request.user.tenant_id) \
.AndReturn(self.routers.list())
if 'floating_ips' in targets:
api.neutron.floating_ip_supported(IsA(http.HttpRequest)) \
.AndReturn(True)
if 'floatingip' in targets:
api.neutron.tenant_floating_ip_list(IsA(http.HttpRequest)) \
.AndReturn(self.floating_ips.list())
if 'security_groups' in targets:
if 'security_group' in targets:
api.neutron.security_group_list(IsA(http.HttpRequest)) \
.AndReturn(self.security_groups.list())

@@ -508,16 +506,16 @@ class QuotaTests(test.APITestCase):
fip_used = len(self.floating_ips.list())
sg_used = len(self.security_groups.list())
expected = {
'networks': {'used': network_used, 'quota': 10,
'available': 10 - network_used},
'subnets': {'used': subnet_used, 'quota': 10,
'available': 10 - subnet_used},
'routers': {'used': router_used, 'quota': 10,
'available': 10 - router_used},
'security_groups': {'used': sg_used, 'quota': 20,
'available': 20 - sg_used},
'floating_ips': {'used': fip_used, 'quota': 50,
'available': 50 - fip_used},
'network': {'used': network_used, 'quota': 10,
'available': 10 - network_used},
'subnet': {'used': subnet_used, 'quota': 10,
'available': 10 - subnet_used},
'router': {'used': router_used, 'quota': 10,
'available': 10 - router_used},
'security_group': {'used': sg_used, 'quota': 20,
'available': 20 - sg_used},
'floatingip': {'used': fip_used, 'quota': 50,
'available': 50 - fip_used},
}
expected = dict((k, v) for k, v in expected.items() if k in targets)


+ 32
- 100
openstack_dashboard/usage/quotas.py View File

@@ -235,33 +235,10 @@ def _get_neutron_quota_data(request, qs, disabled_quotas, tenant_id):
tenant_id = tenant_id or request.user.tenant_id
neutron_quotas = neutron.tenant_quota_get(request, tenant_id)

if 'floatingip' not in disabled_quotas:
# Rename floatingip to floating_ips since that's how it's
# expected in some places (e.g. Security & Access' Floating IPs)
fips_quota = neutron_quotas.get('floatingip').limit
qs.add(base.QuotaSet({'floating_ips': fips_quota}))

if 'security_group' not in disabled_quotas:
# Rename security_group to security_groups since that's how it's
# expected in some places (e.g. Security & Access' Security Groups)
sec_quota = neutron_quotas.get('security_group').limit
qs.add(base.QuotaSet({'security_groups': sec_quota}))

if 'network' not in disabled_quotas:
net_quota = neutron_quotas.get('network').limit
qs.add(base.QuotaSet({'networks': net_quota}))

if 'subnet' not in disabled_quotas:
net_quota = neutron_quotas.get('subnet').limit
qs.add(base.QuotaSet({'subnets': net_quota}))

if 'port' not in disabled_quotas:
net_quota = neutron_quotas.get('port').limit
qs.add(base.QuotaSet({'ports': net_quota}))

if 'router' not in disabled_quotas:
router_quota = neutron_quotas.get('router').limit
qs.add(base.QuotaSet({'routers': router_quota}))
for quota_name in NEUTRON_QUOTA_FIELDS:
if quota_name not in disabled_quotas:
quota_data = neutron_quotas.get(quota_name).limit
qs.add(base.QuotaSet({quota_name: quota_data}))

return qs

@@ -357,19 +334,12 @@ def _get_tenant_network_usages(request, usages, disabled_quotas, tenant_id):

if neutron.is_extension_supported(request, 'quota_details'):
details = neutron.tenant_quota_detail_get(request, tenant_id)
for name, neutron_name in (
('floating_ips', 'floatingip'),
('security_groups', 'security_group'),
('security_group_rules', 'security_group_rule'),
('networks', 'network'),
('subnets', 'subnet'),
('ports', 'port'),
('routers', 'router')):
if neutron_name in disabled_quotas:
for quota_name in NEUTRON_QUOTA_FIELDS:
if quota_name in disabled_quotas:
continue
detail = details[neutron_name]
usages.add_quota(base.Quota(name, detail['limit']))
usages.tally(name, detail['used'] + detail['reserved'])
detail = details[quota_name]
usages.add_quota(base.Quota(quota_name, detail['limit']))
usages.tally(quota_name, detail['used'] + detail['reserved'])
else:
_get_tenant_network_usages_legacy(
request, usages, disabled_quotas, tenant_id)
@@ -377,43 +347,30 @@ def _get_tenant_network_usages(request, usages, disabled_quotas, tenant_id):

def _get_tenant_network_usages_legacy(request, usages, disabled_quotas,
tenant_id):
enabled_quotas = NEUTRON_QUOTA_FIELDS - disabled_quotas
qs = base.QuotaSet()
_get_neutron_quota_data(request, qs, disabled_quotas, tenant_id)
for quota in qs:
usages.add_quota(quota)

# NOTE(amotoki): floatingip is Neutron quota and floating_ips is
# Nova quota. We need to check both.
if {'floatingip', 'floating_ips'} & enabled_quotas:
floating_ips = []
try:
if neutron.floating_ip_supported(request):
floating_ips = neutron.tenant_floating_ip_list(request)
except Exception:
pass
usages.tally('floating_ips', len(floating_ips))

if 'security_group' not in disabled_quotas:
security_groups = []
security_groups = neutron.security_group_list(request)
usages.tally('security_groups', len(security_groups))

if 'network' not in disabled_quotas:
networks = neutron.network_list(request, tenant_id=tenant_id)
usages.tally('networks', len(networks))

if 'subnet' not in disabled_quotas:
subnets = neutron.subnet_list(request, tenant_id=tenant_id)
usages.tally('subnets', len(subnets))

if 'port' not in disabled_quotas:
ports = neutron.port_list(request, tenant_id=tenant_id)
usages.tally('ports', len(ports))

if 'router' not in disabled_quotas:
routers = neutron.router_list(request, tenant_id=tenant_id)
usages.tally('routers', len(routers))
# TODO(amotoki): Add security_group_rule?
resource_lister = {
'network': (neutron.network_list, {'tenant_id': tenant_id}),
'subnet': (neutron.subnet_list, {'tenant_id': tenant_id}),
'port': (neutron.port_list, {'tenant_id': tenant_id}),
'router': (neutron.router_list, {'tenant_id': tenant_id}),
'floatingip': (neutron.tenant_floating_ip_list, {}),
'security_group': (neutron.security_group_list, {}),
}

for quota_name, lister_info in resource_lister.items():
if quota_name not in disabled_quotas:
lister = lister_info[0]
kwargs = lister_info[1]
try:
resources = lister(request, **kwargs)
except Exception:
resources = []
usages.tally(quota_name, len(resources))


@profiler.trace
@@ -435,34 +392,6 @@ def _get_tenant_volume_usages(request, usages, disabled_quotas, tenant_id):
disabled_quotas)


# Singular form key is used as quota field in the Neutron API.
# We convert it explicitly here.
# NOTE(amotoki): It is better to be converted in the horizon API wrapper
# layer. Ideally the REST APIs of back-end services are consistent.
NETWORK_QUOTA_API_KEY_MAP = {
'floating_ips': ['floatingip'],
'networks': ['network'],
'ports': ['port'],
'routers': ['router'],
'security_group_rules': ['security_group_rule'],
'security_groups': ['security_group'],
'subnets': ['subnet'],
}


def _convert_targets_to_quota_keys(targets):
quota_keys = set()
for target in targets:
if target in NETWORK_QUOTA_API_KEY_MAP:
quota_keys.update(NETWORK_QUOTA_API_KEY_MAP[target])
continue
if target in QUOTA_FIELDS:
quota_keys.add(target)
continue
raise ValueError('"%s" is not a valid quota field name.' % target)
return quota_keys


# TODO(amotoki): Merge tenant_quota_usages and tenant_limit_usages.
# These two functions are similar. There seems no reason to have both.

@@ -483,8 +412,11 @@ def tenant_quota_usages(request, tenant_id=None, targets=None):
usages = QuotaUsage()

if targets:
if set(targets) - QUOTA_FIELDS:
raise ValueError('Unknown quota field names are included: %s'
% set(targets) - QUOTA_FIELDS)
enabled_quotas = set(QUOTA_FIELDS) - disabled_quotas
enabled_quotas &= _convert_targets_to_quota_keys(targets)
enabled_quotas &= set(targets)
disabled_quotas = set(QUOTA_FIELDS) - enabled_quotas

_get_tenant_compute_usages(request, usages, disabled_quotas, tenant_id)

Loading…
Cancel
Save