Correct the subnets quota check in admin networks panel

Currently when checking the subnets quota in admin networks table,
the current tenant subnets quota is checked, while the subnet is
created, using the tenant of the selected network[1], this doesn't
look the same. Similarly, in the network details subnets table,
the creation of subnets actions lacks quota checking.

[1] https://github.com/openstack/horizon/blob/master/openstack_dashboard/dashboards/admin/networks/subnets/workflows.py#L75

Change-Id: Ifb88b97168fc4f500e4bb15658f96363ddc7651f
Closes-Bug:#1719606
This commit is contained in:
wei.ying 2017-09-30 14:10:10 +08:00
parent a2bf885519
commit b5bd7589e6
4 changed files with 84 additions and 49 deletions

View File

@ -28,6 +28,7 @@ from openstack_dashboard.dashboards.project.networks.subnets \
import tables as proj_tables
from openstack_dashboard.dashboards.project.networks.subnets.tabs \
import SubnetsTab as project_tabs_subnets_tab
from openstack_dashboard.usage import quotas
LOG = logging.getLogger(__name__)
@ -76,6 +77,23 @@ class CreateSubnet(proj_tables.SubnetPolicyTargetMixin, tables.LinkAction):
network_id = self.table.kwargs['network_id']
return reverse(self.url, args=(network_id,))
def allowed(self, request, datum=None):
network = self.table._get_network()
usages = quotas.tenant_quota_usages(
request, tenant_id=network.tenant_id, targets=('subnets', ))
# when Settings.OPENSTACK_NEUTRON_NETWORK['enable_quotas'] = False
# usages["subnets'] is empty
if usages.get('subnets', {}).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)')
else:
self.verbose_name = _('Create Subnet')
self.classes = [c for c in self.classes if c != 'disabled']
return True
class UpdateSubnet(proj_tables.SubnetPolicyTargetMixin, tables.LinkAction):
name = "update"

View File

@ -409,18 +409,18 @@ class NetworkSubnetTests(test.BaseAdminViewTests):
def _test_network_detail_ip_availability_exception(self,
mac_learning=False):
network_id = self.networks.first().id
quota_data = self.quota_usages.first()
network = self.networks.first()
quota_data = self.neutron_quota_usages.first()
api.neutron.is_extension_supported(
IsA(http.HttpRequest),
'network-ip-availability').AndReturn(True)
api.neutron.show_network_ip_availability(IsA(http.HttpRequest),
network_id).\
network.id).\
MultipleTimes().AndRaise(self.exceptions.neutron)
api.neutron.network_get(IsA(http.HttpRequest), network_id).\
AndReturn(self.networks.first())
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).\
api.neutron.subnet_list(IsA(http.HttpRequest), network_id=network.id).\
AndReturn([self.subnets.first()])
api.neutron.is_extension_supported(IsA(http.HttpRequest),
'mac-learning') \
@ -432,12 +432,12 @@ class NetworkSubnetTests(test.BaseAdminViewTests):
'dhcp_agent_scheduler')\
.MultipleTimes().AndReturn(True)
quotas.tenant_quota_usages(
IsA(http.HttpRequest), targets=('subnets',)) \
.MultipleTimes().AndReturn(quota_data)
IsA(http.HttpRequest), tenant_id=network.tenant_id,
targets=('subnets',)).MultipleTimes().AndReturn(quota_data)
self.mox.ReplayAll()
from django.utils.http import urlunquote
url = urlunquote(reverse('horizon:admin:networks:subnets_tab',
args=[network_id]))
args=[network.id]))
res = self.client.get(url)
self.assertTemplateUsed(res, 'horizon/common/_detail.html')
subnets = res.context['subnets_table'].data

View File

@ -27,6 +27,7 @@ from openstack_dashboard import api
from openstack_dashboard.dashboards.project.networks \
import tables as project_tables
from openstack_dashboard import policy
from openstack_dashboard.usage import quotas
LOG = logging.getLogger(__name__)
@ -82,6 +83,22 @@ class EditNetwork(policy.PolicyTargetMixin, tables.LinkAction):
class CreateSubnet(project_tables.CreateSubnet):
url = "horizon:admin:networks:createsubnet"
def allowed(self, request, datum=None):
usages = quotas.tenant_quota_usages(
request, tenant_id=datum.tenant_id, targets=('subnets', ))
# when Settings.OPENSTACK_NEUTRON_NETWORK['enable_quotas'] = False
# usages["subnets'] is empty
if usages.get('subnets', {}).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)')
else:
self.verbose_name = _('Create Subnet')
self.classes = [c for c in self.classes if c != 'disabled']
return True
DISPLAY_CHOICES = (
("up", pgettext_lazy("Admin state of a Network", u"UP")),

View File

@ -44,6 +44,9 @@ class NetworkTests(test.BaseAdminViewTests):
api.keystone.tenant_list(IsA(http.HttpRequest))\
.AndReturn([tenants, False])
for network in self.networks.list():
usage.quotas.tenant_quota_usages(
IsA(http.HttpRequest), tenant_id=network.tenant_id,
targets=('subnets', )).AndReturn(quota_data)
api.neutron.list_dhcp_agent_hosting_networks(IsA(http.HttpRequest),
network.id)\
.AndReturn(self.agents.list())
@ -54,9 +57,6 @@ class NetworkTests(test.BaseAdminViewTests):
api.neutron.is_extension_supported(
IsA(http.HttpRequest),
'dhcp_agent_scheduler').AndReturn(True)
usage.quotas.tenant_quota_usages(
IsA(http.HttpRequest), targets=('subnets', )) \
.MultipleTimes().AndReturn(quota_data)
self.mox.ReplayAll()
res = self.client.get(INDEX_URL)
@ -106,9 +106,9 @@ class NetworkTests(test.BaseAdminViewTests):
'is_extension_supported'),
usage.quotas: ('tenant_quota_usages',)})
def test_network_detail_new(self, mac_learning=False):
network_id = self.networks.first().id
network = self.networks.first()
quota_data = self.quota_usages.first()
api.neutron.network_get(IsA(http.HttpRequest), network_id) \
api.neutron.network_get(IsA(http.HttpRequest), network.id) \
.MultipleTimes().AndReturn(self.networks.first())
api.neutron.is_extension_supported(IsA(http.HttpRequest),
'network-ip-availability') \
@ -121,11 +121,11 @@ class NetworkTests(test.BaseAdminViewTests):
IsA(http.HttpRequest),
'dhcp_agent_scheduler').AndReturn(True)
usage.quotas.tenant_quota_usages(
IsA(http.HttpRequest), targets=('subnets',)) \
.MultipleTimes().AndReturn(quota_data)
IsA(http.HttpRequest), tenant_id=network.tenant_id,
targets=('subnets',)).MultipleTimes().AndReturn(quota_data)
self.mox.ReplayAll()
url = urlunquote(reverse('horizon:admin:networks:detail',
args=[network_id]))
args=[network.id]))
res = self.client.get(url)
network = res.context['network']
@ -135,15 +135,15 @@ class NetworkTests(test.BaseAdminViewTests):
self.assertTemplateUsed(res, 'horizon/common/_detail.html')
def _test_network_detail_subnets_tab(self, mac_learning=False):
network_id = self.networks.first().id
network = self.networks.first()
ip_availability = self.ip_availability.get()
quota_data = self.quota_usages.first()
api.neutron.show_network_ip_availability(IsA(http.HttpRequest),
network_id).\
network.id).\
MultipleTimes().AndReturn(ip_availability)
api.neutron.network_get(IsA(http.HttpRequest), network_id)\
.AndReturn(self.networks.first())
api.neutron.subnet_list(IsA(http.HttpRequest), network_id=network_id)\
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)\
.AndReturn([self.subnets.first()])
api.neutron.is_extension_supported(
IsA(http.HttpRequest),
@ -159,11 +159,11 @@ class NetworkTests(test.BaseAdminViewTests):
IsA(http.HttpRequest),
'dhcp_agent_scheduler').AndReturn(True)
usage.quotas.tenant_quota_usages(
IsA(http.HttpRequest), targets=('subnets',)) \
.MultipleTimes().AndReturn(quota_data)
IsA(http.HttpRequest), tenant_id=network.tenant_id,
targets=('subnets',)).MultipleTimes().AndReturn(quota_data)
self.mox.ReplayAll()
url = urlunquote(reverse('horizon:admin:networks:subnets_tab',
args=[network_id]))
args=[network.id]))
res = self.client.get(url)
self.assertTemplateUsed(res, 'horizon/common/_detail.html')
@ -196,8 +196,8 @@ class NetworkTests(test.BaseAdminViewTests):
IsA(http.HttpRequest),
'dhcp_agent_scheduler').AndReturn(True)
usage.quotas.tenant_quota_usages(
IsA(http.HttpRequest), targets=('subnets',)) \
.MultipleTimes().AndReturn(quota_data)
IsA(http.HttpRequest), tenant_id=network.tenant_id,
targets=('subnets',)).MultipleTimes().AndReturn(quota_data)
self.mox.ReplayAll()
url = reverse('horizon:admin:networks:ports_tab',
@ -215,7 +215,7 @@ class NetworkTests(test.BaseAdminViewTests):
'list_dhcp_agent_hosting_networks',),
usage.quotas: ('tenant_quota_usages',)})
def test_network_detail_agents_tab(self, mac_learning=False):
network_id = self.networks.first().id
network = self.networks.first()
quota_data = self.quota_usages.first()
api.neutron.is_extension_supported(IsA(http.HttpRequest),
'network-ip-availability') \
@ -225,10 +225,10 @@ class NetworkTests(test.BaseAdminViewTests):
'mac-learning')\
.AndReturn(mac_learning)
api.neutron.list_dhcp_agent_hosting_networks(IsA(http.HttpRequest),
network_id)\
network.id)\
.AndReturn(self.agents.list())
api.neutron.network_get(IsA(http.HttpRequest), network_id)\
.AndReturn(self.networks.first())
api.neutron.network_get(IsA(http.HttpRequest), network.id)\
.MultipleTimes().AndReturn(self.networks.first())
api.neutron.is_extension_supported(
IsA(http.HttpRequest),
'dhcp_agent_scheduler').AndReturn(True)
@ -236,10 +236,10 @@ class NetworkTests(test.BaseAdminViewTests):
IsA(http.HttpRequest),
'dhcp_agent_scheduler').AndReturn(True)
usage.quotas.tenant_quota_usages(
IsA(http.HttpRequest), targets=('subnets', )) \
.MultipleTimes().AndReturn(quota_data)
IsA(http.HttpRequest), tenant_id=network.tenant_id,
targets=('subnets',)).MultipleTimes().AndReturn(quota_data)
self.mox.ReplayAll()
url = reverse('horizon:admin:networks:agents_tab', args=[network_id])
url = reverse('horizon:admin:networks:agents_tab', args=[network.id])
res = self.client.get(urlunquote(url))
self.assertTemplateUsed(res, 'horizon/common/_detail.html')
@ -318,11 +318,11 @@ class NetworkTests(test.BaseAdminViewTests):
def _test_network_detail_subnets_tab_subnet_exception(self,
mac_learning=False):
network_id = self.networks.first().id
network = self.networks.first()
quota_data = self.quota_usages.first()
api.neutron.network_get(IsA(http.HttpRequest), network_id).\
AndReturn(self.networks.first())
api.neutron.subnet_list(IsA(http.HttpRequest), network_id=network_id).\
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).\
AndRaise(self.exceptions.neutron)
api.neutron.is_extension_supported(
IsA(http.HttpRequest),
@ -337,11 +337,11 @@ class NetworkTests(test.BaseAdminViewTests):
IsA(http.HttpRequest),
'dhcp_agent_scheduler').AndReturn(True)
usage.quotas.tenant_quota_usages(
IsA(http.HttpRequest), targets=('subnets',)) \
.MultipleTimes().AndReturn(quota_data)
IsA(http.HttpRequest), tenant_id=network.tenant_id,
targets=('subnets',)).MultipleTimes().AndReturn(quota_data)
self.mox.ReplayAll()
url = urlunquote(reverse('horizon:admin:networks:subnets_tab',
args=[network_id]))
args=[network.id]))
res = self.client.get(url)
self.assertTemplateUsed(res, 'horizon/common/_detail.html')
@ -370,15 +370,15 @@ class NetworkTests(test.BaseAdminViewTests):
def _test_network_detail_subnets_tab_port_exception(self,
mac_learning=False):
network_id = self.networks.first().id
network = self.networks.first()
ip_availability = self.ip_availability.get()
quota_data = self.quota_usages.first()
api.neutron.show_network_ip_availability(IsA(http.HttpRequest),
network_id). \
network.id). \
MultipleTimes().AndReturn(ip_availability)
api.neutron.network_get(IsA(http.HttpRequest), network_id).\
AndReturn(self.networks.first())
api.neutron.subnet_list(IsA(http.HttpRequest), network_id=network_id).\
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).\
AndReturn([self.subnets.first()])
api.neutron.is_extension_supported(
IsA(http.HttpRequest),
@ -393,11 +393,11 @@ class NetworkTests(test.BaseAdminViewTests):
'dhcp_agent_scheduler')\
.AndReturn(True)
usage.quotas.tenant_quota_usages(
IsA(http.HttpRequest), targets=('subnets',)) \
.MultipleTimes().AndReturn(quota_data)
IsA(http.HttpRequest), tenant_id=network.tenant_id,
targets=('subnets',)).MultipleTimes().AndReturn(quota_data)
self.mox.ReplayAll()
url = urlunquote(reverse('horizon:admin:networks:subnets_tab',
args=[network_id]))
args=[network.id]))
res = self.client.get(url)
self.assertTemplateUsed(res, 'horizon/common/_detail.html')