Merge "Revert "Remove the quota check for "Launch Instance" button""

This commit is contained in:
Zuul 2017-10-19 15:42:43 +00:00 committed by Gerrit Code Review
commit 4927f5fae4
2 changed files with 95 additions and 0 deletions

View File

@ -17,6 +17,7 @@ import logging
from django.conf import settings from django.conf import settings
from django.core import urlresolvers from django.core import urlresolvers
from django.http import HttpResponse
from django import shortcuts from django import shortcuts
from django import template from django import template
from django.template.defaultfilters import title from django.template.defaultfilters import title
@ -390,6 +391,36 @@ class LaunchLink(tables.LinkAction):
kwargs['preempt'] = True kwargs['preempt'] = True
super(LaunchLink, self).__init__(attrs, **kwargs) super(LaunchLink, self).__init__(attrs, **kwargs)
def allowed(self, request, datum):
try:
limits = api.nova.tenant_absolute_limits(request, reserved=True)
instances_available = limits['maxTotalInstances'] \
- limits['totalInstancesUsed']
cores_available = limits['maxTotalCores'] \
- limits['totalCoresUsed']
ram_available = limits['maxTotalRAMSize'] - limits['totalRAMUsed']
if instances_available <= 0 or cores_available <= 0 \
or ram_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, ' ',
_("(Quota exceeded)"))
else:
self.verbose_name = _("Launch Instance")
classes = [c for c in self.classes if c != "disabled"]
self.classes = classes
except Exception:
LOG.exception("Failed to retrieve quota information")
# If we can't get the quota information, leave it to the
# API to check when launching
return True # The action should always be displayed
def single(self, table, request, object_id=None):
self.allowed(request, None)
return HttpResponse(self.render(is_table_action=True))
class LaunchLinkNG(LaunchLink): class LaunchLinkNG(LaunchLink):
name = "launch-ng" name = "launch-ng"

View File

@ -149,6 +149,8 @@ class InstanceTests(helpers.ResetImageAPIVersionMixin, helpers.TestCase):
api.nova.server_list(IsA(http.HttpRequest), search_opts=search_opts) \ api.nova.server_list(IsA(http.HttpRequest), search_opts=search_opts) \
.AndReturn([servers, False]) .AndReturn([servers, False])
api.network.servers_update_addresses(IsA(http.HttpRequest), servers) api.network.servers_update_addresses(IsA(http.HttpRequest), servers)
api.nova.tenant_absolute_limits(IsA(http.HttpRequest), reserved=True) \
.MultipleTimes().AndReturn(self.limits['absolute'])
api.neutron.floating_ip_supported(IsA(http.HttpRequest)) \ api.neutron.floating_ip_supported(IsA(http.HttpRequest)) \
.MultipleTimes().AndReturn(True) .MultipleTimes().AndReturn(True)
api.neutron.floating_ip_simple_associate_supported( api.neutron.floating_ip_simple_associate_supported(
@ -182,6 +184,8 @@ class InstanceTests(helpers.ResetImageAPIVersionMixin, helpers.TestCase):
.AndReturn(images) .AndReturn(images)
api.nova.server_list(IsA(http.HttpRequest), search_opts=search_opts) \ api.nova.server_list(IsA(http.HttpRequest), search_opts=search_opts) \
.AndRaise(self.exceptions.nova) .AndRaise(self.exceptions.nova)
api.nova.tenant_absolute_limits(IsA(http.HttpRequest), reserved=True) \
.MultipleTimes().AndReturn(self.limits['absolute'])
self.mox.ReplayAll() self.mox.ReplayAll()
@ -217,6 +221,8 @@ class InstanceTests(helpers.ResetImageAPIVersionMixin, helpers.TestCase):
.AndRaise(self.exceptions.nova) .AndRaise(self.exceptions.nova)
api.glance.image_list_detailed(IgnoreArg()) \ api.glance.image_list_detailed(IgnoreArg()) \
.AndReturn((self.images.list(), False, False)) .AndReturn((self.images.list(), False, False))
api.nova.tenant_absolute_limits(IsA(http.HttpRequest), reserved=True) \
.MultipleTimes().AndReturn(self.limits['absolute'])
api.neutron.floating_ip_supported(IsA(http.HttpRequest)) \ api.neutron.floating_ip_supported(IsA(http.HttpRequest)) \
.MultipleTimes().AndReturn(True) .MultipleTimes().AndReturn(True)
api.neutron.floating_ip_simple_associate_supported( api.neutron.floating_ip_simple_associate_supported(
@ -261,6 +267,8 @@ class InstanceTests(helpers.ResetImageAPIVersionMixin, helpers.TestCase):
api.nova.server_list(IsA(http.HttpRequest), search_opts=search_opts) \ api.nova.server_list(IsA(http.HttpRequest), search_opts=search_opts) \
.AndReturn([servers, False]) .AndReturn([servers, False])
api.network.servers_update_addresses(IsA(http.HttpRequest), servers) api.network.servers_update_addresses(IsA(http.HttpRequest), servers)
api.nova.tenant_absolute_limits(IsA(http.HttpRequest), reserved=True) \
.MultipleTimes().AndReturn(self.limits['absolute'])
api.neutron.floating_ip_supported(IsA(http.HttpRequest)) \ api.neutron.floating_ip_supported(IsA(http.HttpRequest)) \
.MultipleTimes().AndReturn(True) .MultipleTimes().AndReturn(True)
api.neutron.floating_ip_simple_associate_supported( api.neutron.floating_ip_simple_associate_supported(
@ -1444,6 +1452,8 @@ class InstanceTests(helpers.ResetImageAPIVersionMixin, helpers.TestCase):
api.nova.server_list(IsA(http.HttpRequest), search_opts=search_opts) \ api.nova.server_list(IsA(http.HttpRequest), search_opts=search_opts) \
.AndReturn([servers, False]) .AndReturn([servers, False])
api.network.servers_update_addresses(IsA(http.HttpRequest), servers) api.network.servers_update_addresses(IsA(http.HttpRequest), servers)
api.nova.tenant_absolute_limits(IsA(http.HttpRequest), reserved=True) \
.MultipleTimes().AndReturn(self.limits['absolute'])
api.neutron.floating_ip_supported(IsA(http.HttpRequest)) \ api.neutron.floating_ip_supported(IsA(http.HttpRequest)) \
.MultipleTimes().AndReturn(True) .MultipleTimes().AndReturn(True)
api.neutron.floating_ip_simple_associate_supported( api.neutron.floating_ip_simple_associate_supported(
@ -3339,6 +3349,8 @@ class InstanceTests(helpers.ResetImageAPIVersionMixin, helpers.TestCase):
api.nova.server_list(IsA(http.HttpRequest), search_opts=search_opts) \ api.nova.server_list(IsA(http.HttpRequest), search_opts=search_opts) \
.AndReturn([servers, False]) .AndReturn([servers, False])
api.network.servers_update_addresses(IsA(http.HttpRequest), servers) api.network.servers_update_addresses(IsA(http.HttpRequest), servers)
api.nova.tenant_absolute_limits(IsA(http.HttpRequest), reserved=True) \
.MultipleTimes().AndReturn(limits)
api.neutron.floating_ip_supported(IsA(http.HttpRequest)) \ api.neutron.floating_ip_supported(IsA(http.HttpRequest)) \
.MultipleTimes().AndReturn(True) .MultipleTimes().AndReturn(True)
api.neutron.floating_ip_simple_associate_supported( api.neutron.floating_ip_simple_associate_supported(
@ -3358,6 +3370,54 @@ class InstanceTests(helpers.ResetImageAPIVersionMixin, helpers.TestCase):
self.assertEqual((('compute', 'os_compute_api:servers:create'),), self.assertEqual((('compute', 'os_compute_api:servers:create'),),
launch_action.policy_rules) launch_action.policy_rules)
@helpers.create_stubs({
api.nova: ('flavor_list', 'server_list', 'tenant_absolute_limits',
'extension_supported', 'is_feature_available',),
api.glance: ('image_list_detailed',),
api.neutron: ('floating_ip_simple_associate_supported',
'floating_ip_supported',),
api.network: ('servers_update_addresses',),
})
def test_launch_button_disabled_when_quota_exceeded(self):
servers = self.servers.list()
limits = self.limits['absolute']
limits['totalInstancesUsed'] = limits['maxTotalInstances']
api.nova.extension_supported('AdminActions', IsA(http.HttpRequest)) \
.MultipleTimes().AndReturn(True)
api.nova.is_feature_available(
IsA(http.HttpRequest), 'locked_attribute'
).MultipleTimes().AndReturn(True)
api.nova.extension_supported('Shelve', IsA(http.HttpRequest)) \
.MultipleTimes().AndReturn(True)
api.nova.flavor_list(IsA(http.HttpRequest)) \
.AndReturn(self.flavors.list())
api.glance.image_list_detailed(IgnoreArg()) \
.AndReturn((self.images.list(), False, False))
search_opts = {'marker': None, 'paginate': True}
api.nova.server_list(IsA(http.HttpRequest), search_opts=search_opts) \
.AndReturn([servers, False])
api.network.servers_update_addresses(IsA(http.HttpRequest), servers)
api.nova.tenant_absolute_limits(IsA(http.HttpRequest), reserved=True) \
.MultipleTimes().AndReturn(limits)
api.neutron.floating_ip_supported(IsA(http.HttpRequest)) \
.MultipleTimes().AndReturn(True)
api.neutron.floating_ip_simple_associate_supported(
IsA(http.HttpRequest)).MultipleTimes().AndReturn(True)
self.mox.ReplayAll()
tables.LaunchLink()
res = self.client.get(INDEX_URL)
launch_action = self.getAndAssertTableAction(
res, 'instances', 'launch-ng')
self.assertIn('disabled', launch_action.classes,
'The launch button should be disabled')
self.assertEqual('Launch Instance (Quota exceeded)',
six.text_type(launch_action.verbose_name))
@helpers.create_stubs({api.glance: ('image_list_detailed',), @helpers.create_stubs({api.glance: ('image_list_detailed',),
api.neutron: ('network_list', api.neutron: ('network_list',
'port_list_with_trunk_types', 'port_list_with_trunk_types',
@ -3492,6 +3552,8 @@ class InstanceTests(helpers.ResetImageAPIVersionMixin, helpers.TestCase):
api.nova.server_list(IsA(http.HttpRequest), search_opts=search_opts) \ api.nova.server_list(IsA(http.HttpRequest), search_opts=search_opts) \
.AndReturn([servers, False]) .AndReturn([servers, False])
api.network.servers_update_addresses(IsA(http.HttpRequest), servers) api.network.servers_update_addresses(IsA(http.HttpRequest), servers)
api.nova.tenant_absolute_limits(IsA(http.HttpRequest), reserved=True) \
.MultipleTimes().AndReturn(self.limits['absolute'])
api.neutron.floating_ip_supported(IsA(http.HttpRequest)) \ api.neutron.floating_ip_supported(IsA(http.HttpRequest)) \
.MultipleTimes().AndReturn(True) .MultipleTimes().AndReturn(True)
api.neutron.floating_ip_simple_associate_supported( api.neutron.floating_ip_simple_associate_supported(
@ -3969,6 +4031,8 @@ class InstanceTests(helpers.ResetImageAPIVersionMixin, helpers.TestCase):
api.network.servers_update_addresses( api.network.servers_update_addresses(
IsA(http.HttpRequest), servers[page_size:]) IsA(http.HttpRequest), servers[page_size:])
api.nova.tenant_absolute_limits(IsA(http.HttpRequest), reserved=True) \
.MultipleTimes().AndReturn(self.limits['absolute'])
api.neutron.floating_ip_supported(IsA(http.HttpRequest)) \ api.neutron.floating_ip_supported(IsA(http.HttpRequest)) \
.MultipleTimes().AndReturn(True) .MultipleTimes().AndReturn(True)
api.neutron.floating_ip_simple_associate_supported( api.neutron.floating_ip_simple_associate_supported(