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.core import urlresolvers
from django.http import HttpResponse
from django import shortcuts
from django import template
from django.template.defaultfilters import title
@ -390,6 +391,36 @@ class LaunchLink(tables.LinkAction):
kwargs['preempt'] = True
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):
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) \
.AndReturn([servers, False])
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)) \
.MultipleTimes().AndReturn(True)
api.neutron.floating_ip_simple_associate_supported(
@ -182,6 +184,8 @@ class InstanceTests(helpers.ResetImageAPIVersionMixin, helpers.TestCase):
.AndReturn(images)
api.nova.server_list(IsA(http.HttpRequest), search_opts=search_opts) \
.AndRaise(self.exceptions.nova)
api.nova.tenant_absolute_limits(IsA(http.HttpRequest), reserved=True) \
.MultipleTimes().AndReturn(self.limits['absolute'])
self.mox.ReplayAll()
@ -217,6 +221,8 @@ class InstanceTests(helpers.ResetImageAPIVersionMixin, helpers.TestCase):
.AndRaise(self.exceptions.nova)
api.glance.image_list_detailed(IgnoreArg()) \
.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)) \
.MultipleTimes().AndReturn(True)
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) \
.AndReturn([servers, False])
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)) \
.MultipleTimes().AndReturn(True)
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) \
.AndReturn([servers, False])
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)) \
.MultipleTimes().AndReturn(True)
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) \
.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(
@ -3358,6 +3370,54 @@ class InstanceTests(helpers.ResetImageAPIVersionMixin, helpers.TestCase):
self.assertEqual((('compute', 'os_compute_api:servers:create'),),
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',),
api.neutron: ('network_list',
'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) \
.AndReturn([servers, False])
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)) \
.MultipleTimes().AndReturn(True)
api.neutron.floating_ip_simple_associate_supported(
@ -3969,6 +4031,8 @@ class InstanceTests(helpers.ResetImageAPIVersionMixin, helpers.TestCase):
api.network.servers_update_addresses(
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)) \
.MultipleTimes().AndReturn(True)
api.neutron.floating_ip_simple_associate_supported(