Browse Source

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

Zuul 1 year ago
parent
commit
4927f5fae4

+ 31
- 0
openstack_dashboard/dashboards/project/instances/tables.py View File

@@ -17,6 +17,7 @@ import logging
17 17
 
18 18
 from django.conf import settings
19 19
 from django.core import urlresolvers
20
+from django.http import HttpResponse
20 21
 from django import shortcuts
21 22
 from django import template
22 23
 from django.template.defaultfilters import title
@@ -390,6 +391,36 @@ class LaunchLink(tables.LinkAction):
390 391
         kwargs['preempt'] = True
391 392
         super(LaunchLink, self).__init__(attrs, **kwargs)
392 393
 
394
+    def allowed(self, request, datum):
395
+        try:
396
+            limits = api.nova.tenant_absolute_limits(request, reserved=True)
397
+
398
+            instances_available = limits['maxTotalInstances'] \
399
+                - limits['totalInstancesUsed']
400
+            cores_available = limits['maxTotalCores'] \
401
+                - limits['totalCoresUsed']
402
+            ram_available = limits['maxTotalRAMSize'] - limits['totalRAMUsed']
403
+
404
+            if instances_available <= 0 or cores_available <= 0 \
405
+                    or ram_available <= 0:
406
+                if "disabled" not in self.classes:
407
+                    self.classes = [c for c in self.classes] + ['disabled']
408
+                    self.verbose_name = string_concat(self.verbose_name, ' ',
409
+                                                      _("(Quota exceeded)"))
410
+            else:
411
+                self.verbose_name = _("Launch Instance")
412
+                classes = [c for c in self.classes if c != "disabled"]
413
+                self.classes = classes
414
+        except Exception:
415
+            LOG.exception("Failed to retrieve quota information")
416
+            # If we can't get the quota information, leave it to the
417
+            # API to check when launching
418
+        return True  # The action should always be displayed
419
+
420
+    def single(self, table, request, object_id=None):
421
+        self.allowed(request, None)
422
+        return HttpResponse(self.render(is_table_action=True))
423
+
393 424
 
394 425
 class LaunchLinkNG(LaunchLink):
395 426
     name = "launch-ng"

+ 64
- 0
openstack_dashboard/dashboards/project/instances/tests.py View File

@@ -149,6 +149,8 @@ class InstanceTests(helpers.ResetImageAPIVersionMixin, helpers.TestCase):
149 149
         api.nova.server_list(IsA(http.HttpRequest), search_opts=search_opts) \
150 150
             .AndReturn([servers, False])
151 151
         api.network.servers_update_addresses(IsA(http.HttpRequest), servers)
152
+        api.nova.tenant_absolute_limits(IsA(http.HttpRequest), reserved=True) \
153
+           .MultipleTimes().AndReturn(self.limits['absolute'])
152 154
         api.neutron.floating_ip_supported(IsA(http.HttpRequest)) \
153 155
             .MultipleTimes().AndReturn(True)
154 156
         api.neutron.floating_ip_simple_associate_supported(
@@ -182,6 +184,8 @@ class InstanceTests(helpers.ResetImageAPIVersionMixin, helpers.TestCase):
182 184
             .AndReturn(images)
183 185
         api.nova.server_list(IsA(http.HttpRequest), search_opts=search_opts) \
184 186
             .AndRaise(self.exceptions.nova)
187
+        api.nova.tenant_absolute_limits(IsA(http.HttpRequest), reserved=True) \
188
+           .MultipleTimes().AndReturn(self.limits['absolute'])
185 189
 
186 190
         self.mox.ReplayAll()
187 191
 
@@ -217,6 +221,8 @@ class InstanceTests(helpers.ResetImageAPIVersionMixin, helpers.TestCase):
217 221
             .AndRaise(self.exceptions.nova)
218 222
         api.glance.image_list_detailed(IgnoreArg()) \
219 223
             .AndReturn((self.images.list(), False, False))
224
+        api.nova.tenant_absolute_limits(IsA(http.HttpRequest), reserved=True) \
225
+           .MultipleTimes().AndReturn(self.limits['absolute'])
220 226
         api.neutron.floating_ip_supported(IsA(http.HttpRequest)) \
221 227
             .MultipleTimes().AndReturn(True)
222 228
         api.neutron.floating_ip_simple_associate_supported(
@@ -261,6 +267,8 @@ class InstanceTests(helpers.ResetImageAPIVersionMixin, helpers.TestCase):
261 267
         api.nova.server_list(IsA(http.HttpRequest), search_opts=search_opts) \
262 268
             .AndReturn([servers, False])
263 269
         api.network.servers_update_addresses(IsA(http.HttpRequest), servers)
270
+        api.nova.tenant_absolute_limits(IsA(http.HttpRequest), reserved=True) \
271
+           .MultipleTimes().AndReturn(self.limits['absolute'])
264 272
         api.neutron.floating_ip_supported(IsA(http.HttpRequest)) \
265 273
             .MultipleTimes().AndReturn(True)
266 274
         api.neutron.floating_ip_simple_associate_supported(
@@ -1444,6 +1452,8 @@ class InstanceTests(helpers.ResetImageAPIVersionMixin, helpers.TestCase):
1444 1452
         api.nova.server_list(IsA(http.HttpRequest), search_opts=search_opts) \
1445 1453
             .AndReturn([servers, False])
1446 1454
         api.network.servers_update_addresses(IsA(http.HttpRequest), servers)
1455
+        api.nova.tenant_absolute_limits(IsA(http.HttpRequest), reserved=True) \
1456
+           .MultipleTimes().AndReturn(self.limits['absolute'])
1447 1457
         api.neutron.floating_ip_supported(IsA(http.HttpRequest)) \
1448 1458
             .MultipleTimes().AndReturn(True)
1449 1459
         api.neutron.floating_ip_simple_associate_supported(
@@ -3339,6 +3349,8 @@ class InstanceTests(helpers.ResetImageAPIVersionMixin, helpers.TestCase):
3339 3349
         api.nova.server_list(IsA(http.HttpRequest), search_opts=search_opts) \
3340 3350
             .AndReturn([servers, False])
3341 3351
         api.network.servers_update_addresses(IsA(http.HttpRequest), servers)
3352
+        api.nova.tenant_absolute_limits(IsA(http.HttpRequest), reserved=True) \
3353
+            .MultipleTimes().AndReturn(limits)
3342 3354
         api.neutron.floating_ip_supported(IsA(http.HttpRequest)) \
3343 3355
             .MultipleTimes().AndReturn(True)
3344 3356
         api.neutron.floating_ip_simple_associate_supported(
@@ -3358,6 +3370,54 @@ class InstanceTests(helpers.ResetImageAPIVersionMixin, helpers.TestCase):
3358 3370
         self.assertEqual((('compute', 'os_compute_api:servers:create'),),
3359 3371
                          launch_action.policy_rules)
3360 3372
 
3373
+    @helpers.create_stubs({
3374
+        api.nova: ('flavor_list', 'server_list', 'tenant_absolute_limits',
3375
+                   'extension_supported', 'is_feature_available',),
3376
+        api.glance: ('image_list_detailed',),
3377
+        api.neutron: ('floating_ip_simple_associate_supported',
3378
+                      'floating_ip_supported',),
3379
+        api.network: ('servers_update_addresses',),
3380
+    })
3381
+    def test_launch_button_disabled_when_quota_exceeded(self):
3382
+        servers = self.servers.list()
3383
+        limits = self.limits['absolute']
3384
+        limits['totalInstancesUsed'] = limits['maxTotalInstances']
3385
+
3386
+        api.nova.extension_supported('AdminActions', IsA(http.HttpRequest)) \
3387
+            .MultipleTimes().AndReturn(True)
3388
+        api.nova.is_feature_available(
3389
+            IsA(http.HttpRequest), 'locked_attribute'
3390
+        ).MultipleTimes().AndReturn(True)
3391
+        api.nova.extension_supported('Shelve', IsA(http.HttpRequest)) \
3392
+            .MultipleTimes().AndReturn(True)
3393
+        api.nova.flavor_list(IsA(http.HttpRequest)) \
3394
+            .AndReturn(self.flavors.list())
3395
+        api.glance.image_list_detailed(IgnoreArg()) \
3396
+            .AndReturn((self.images.list(), False, False))
3397
+        search_opts = {'marker': None, 'paginate': True}
3398
+        api.nova.server_list(IsA(http.HttpRequest), search_opts=search_opts) \
3399
+            .AndReturn([servers, False])
3400
+        api.network.servers_update_addresses(IsA(http.HttpRequest), servers)
3401
+        api.nova.tenant_absolute_limits(IsA(http.HttpRequest), reserved=True) \
3402
+            .MultipleTimes().AndReturn(limits)
3403
+        api.neutron.floating_ip_supported(IsA(http.HttpRequest)) \
3404
+            .MultipleTimes().AndReturn(True)
3405
+        api.neutron.floating_ip_simple_associate_supported(
3406
+            IsA(http.HttpRequest)).MultipleTimes().AndReturn(True)
3407
+
3408
+        self.mox.ReplayAll()
3409
+
3410
+        tables.LaunchLink()
3411
+        res = self.client.get(INDEX_URL)
3412
+
3413
+        launch_action = self.getAndAssertTableAction(
3414
+            res, 'instances', 'launch-ng')
3415
+
3416
+        self.assertIn('disabled', launch_action.classes,
3417
+                      'The launch button should be disabled')
3418
+        self.assertEqual('Launch Instance (Quota exceeded)',
3419
+                         six.text_type(launch_action.verbose_name))
3420
+
3361 3421
     @helpers.create_stubs({api.glance: ('image_list_detailed',),
3362 3422
                            api.neutron: ('network_list',
3363 3423
                                          'port_list_with_trunk_types',
@@ -3492,6 +3552,8 @@ class InstanceTests(helpers.ResetImageAPIVersionMixin, helpers.TestCase):
3492 3552
         api.nova.server_list(IsA(http.HttpRequest), search_opts=search_opts) \
3493 3553
             .AndReturn([servers, False])
3494 3554
         api.network.servers_update_addresses(IsA(http.HttpRequest), servers)
3555
+        api.nova.tenant_absolute_limits(IsA(http.HttpRequest), reserved=True) \
3556
+           .MultipleTimes().AndReturn(self.limits['absolute'])
3495 3557
         api.neutron.floating_ip_supported(IsA(http.HttpRequest)) \
3496 3558
             .MultipleTimes().AndReturn(True)
3497 3559
         api.neutron.floating_ip_simple_associate_supported(
@@ -3969,6 +4031,8 @@ class InstanceTests(helpers.ResetImageAPIVersionMixin, helpers.TestCase):
3969 4031
         api.network.servers_update_addresses(
3970 4032
             IsA(http.HttpRequest), servers[page_size:])
3971 4033
 
4034
+        api.nova.tenant_absolute_limits(IsA(http.HttpRequest), reserved=True) \
4035
+           .MultipleTimes().AndReturn(self.limits['absolute'])
3972 4036
         api.neutron.floating_ip_supported(IsA(http.HttpRequest)) \
3973 4037
             .MultipleTimes().AndReturn(True)
3974 4038
         api.neutron.floating_ip_simple_associate_supported(

Loading…
Cancel
Save