~ubuntu-branches/ubuntu/saucy/nova/saucy-proposed

« back to all changes in this revision

Viewing changes to nova/tests/test_quota.py

  • Committer: Package Import Robot
  • Author(s): Chuck Short
  • Date: 2012-05-24 13:12:53 UTC
  • mfrom: (1.1.55)
  • Revision ID: package-import@ubuntu.com-20120524131253-ommql08fg1en06ut
Tags: 2012.2~f1-0ubuntu1
* New upstream release.
* Prepare for quantal:
  - Dropped debian/patches/upstream/0006-Use-project_id-in-ec2.cloud._format_image.patch
  - Dropped debian/patches/upstream/0005-Populate-image-properties-with-project_id-again.patch
  - Dropped debian/patches/upstream/0004-Fixed-bug-962840-added-a-test-case.patch
  - Dropped debian/patches/upstream/0003-Allow-unprivileged-RADOS-users-to-access-rbd-volumes.patch
  - Dropped debian/patches/upstream/0002-Stop-libvirt-test-from-deleting-instances-dir.patch
  - Dropped debian/patches/upstream/0001-fix-bug-where-nova-ignores-glance-host-in-imageref.patch 
  - Dropped debian/patches/0001-fix-useexisting-deprecation-warnings.patch
* debian/control: Add python-keystone as a dependency. (LP: #907197)
* debian/patches/kombu_tests_timeout.patch: Refreshed.
* debian/nova.conf, debian/nova-common.postinst: Convert to new ini
  file configuration
* debian/patches/nova-manage_flagfile_location.patch: Refreshed

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
#    License for the specific language governing permissions and limitations
17
17
#    under the License.
18
18
 
 
19
import datetime
 
20
 
19
21
from nova import compute
 
22
from nova.compute import instance_types
20
23
from nova import context
21
24
from nova import db
 
25
from nova.db.sqlalchemy import api as sqa_api
 
26
from nova.db.sqlalchemy import models as sqa_models
 
27
from nova import exception
22
28
from nova import flags
23
29
from nova import quota
24
 
from nova import exception
25
30
from nova import rpc
 
31
from nova.scheduler import driver as scheduler_driver
26
32
from nova import test
 
33
from nova import utils
27
34
from nova import volume
28
 
from nova.compute import instance_types
29
 
from nova.scheduler import driver as scheduler_driver
30
35
 
31
36
 
32
37
FLAGS = flags.FLAGS
33
38
 
34
39
 
35
 
class QuotaTestCase(test.TestCase):
 
40
class GetQuotaTestCase(test.TestCase):
 
41
    def setUp(self):
 
42
        super(GetQuotaTestCase, self).setUp()
 
43
        self.flags(quota_instances=10,
 
44
                   quota_cores=20,
 
45
                   quota_ram=50 * 1024,
 
46
                   quota_volumes=10,
 
47
                   quota_gigabytes=1000,
 
48
                   quota_floating_ips=10,
 
49
                   quota_security_groups=10,
 
50
                   quota_security_group_rules=20,
 
51
                   quota_key_pairs=10,
 
52
                   quota_metadata_items=128,
 
53
                   quota_injected_files=5,
 
54
                   quota_injected_file_content_bytes=10 * 1024)
 
55
        self.context = context.RequestContext('admin', 'admin', is_admin=True)
 
56
 
 
57
    def _stub_class(self):
 
58
        def fake_quota_class_get_all_by_name(context, quota_class):
 
59
            result = dict(class_name=quota_class)
 
60
            if quota_class == 'test_class':
 
61
                result.update(
 
62
                    instances=5,
 
63
                    cores=10,
 
64
                    ram=25 * 1024,
 
65
                    volumes=5,
 
66
                    gigabytes=500,
 
67
                    floating_ips=5,
 
68
                    quota_security_groups=10,
 
69
                    quota_security_group_rules=20,
 
70
                    quota_key_pairs=10,
 
71
                    metadata_items=64,
 
72
                    injected_files=2,
 
73
                    injected_file_content_bytes=5 * 1024,
 
74
                    invalid_quota=100,
 
75
                    )
 
76
            return result
 
77
 
 
78
        self.stubs.Set(db, 'quota_class_get_all_by_name',
 
79
                       fake_quota_class_get_all_by_name)
 
80
 
 
81
    def _stub_project(self, override=False):
 
82
        def fake_quota_get_all_by_project(context, project_id):
 
83
            result = dict(project_id=project_id)
 
84
            if override:
 
85
                result.update(
 
86
                    instances=2,
 
87
                    cores=5,
 
88
                    ram=12 * 1024,
 
89
                    volumes=2,
 
90
                    gigabytes=250,
 
91
                    floating_ips=2,
 
92
                    security_groups=5,
 
93
                    security_group_rules=10,
 
94
                    key_pairs=5,
 
95
                    metadata_items=32,
 
96
                    injected_files=1,
 
97
                    injected_file_content_bytes=2 * 1024,
 
98
                    invalid_quota=50,
 
99
                    )
 
100
            return result
 
101
 
 
102
        self.stubs.Set(db, 'quota_get_all_by_project',
 
103
                       fake_quota_get_all_by_project)
 
104
 
 
105
    def test_default_quotas(self):
 
106
        result = quota._get_default_quotas()
 
107
        self.assertEqual(result, dict(
 
108
                instances=10,
 
109
                cores=20,
 
110
                ram=50 * 1024,
 
111
                volumes=10,
 
112
                gigabytes=1000,
 
113
                floating_ips=10,
 
114
                security_groups=10,
 
115
                security_group_rules=20,
 
116
                key_pairs=10,
 
117
                metadata_items=128,
 
118
                injected_files=5,
 
119
                injected_file_content_bytes=10 * 1024,
 
120
                ))
 
121
 
 
122
    def test_default_quotas_unlimited(self):
 
123
        self.flags(quota_instances=-1,
 
124
                   quota_cores=-1,
 
125
                   quota_ram=-1,
 
126
                   quota_volumes=-1,
 
127
                   quota_gigabytes=-1,
 
128
                   quota_floating_ips=-1,
 
129
                   quota_security_groups=-1,
 
130
                   quota_security_group_rules=-1,
 
131
                   quota_key_pairs=-1,
 
132
                   quota_metadata_items=-1,
 
133
                   quota_injected_files=-1,
 
134
                   quota_injected_file_content_bytes=-1)
 
135
        result = quota._get_default_quotas()
 
136
        self.assertEqual(result, dict(
 
137
                instances=-1,
 
138
                cores=-1,
 
139
                ram=-1,
 
140
                volumes=-1,
 
141
                gigabytes=-1,
 
142
                floating_ips=-1,
 
143
                security_groups=-1,
 
144
                security_group_rules=-1,
 
145
                key_pairs=-1,
 
146
                metadata_items=-1,
 
147
                injected_files=-1,
 
148
                injected_file_content_bytes=-1,
 
149
                ))
 
150
 
 
151
    def test_class_quotas_noclass(self):
 
152
        self._stub_class()
 
153
        result = quota.get_class_quotas(self.context, 'noclass')
 
154
        self.assertEqual(result, dict(
 
155
                instances=10,
 
156
                cores=20,
 
157
                ram=50 * 1024,
 
158
                volumes=10,
 
159
                gigabytes=1000,
 
160
                floating_ips=10,
 
161
                security_groups=10,
 
162
                security_group_rules=20,
 
163
                key_pairs=10,
 
164
                metadata_items=128,
 
165
                injected_files=5,
 
166
                injected_file_content_bytes=10 * 1024,
 
167
                ))
 
168
 
 
169
    def test_class_quotas(self):
 
170
        self._stub_class()
 
171
        result = quota.get_class_quotas(self.context, 'test_class')
 
172
        self.assertEqual(result, dict(
 
173
                instances=5,
 
174
                cores=10,
 
175
                ram=25 * 1024,
 
176
                volumes=5,
 
177
                gigabytes=500,
 
178
                floating_ips=5,
 
179
                security_groups=10,
 
180
                security_group_rules=20,
 
181
                key_pairs=10,
 
182
                metadata_items=64,
 
183
                injected_files=2,
 
184
                injected_file_content_bytes=5 * 1024,
 
185
                ))
 
186
 
 
187
    def test_project_quotas_defaults_noclass(self):
 
188
        self._stub_class()
 
189
        self._stub_project()
 
190
        result = quota.get_project_quotas(self.context, 'admin')
 
191
        self.assertEqual(result, dict(
 
192
                instances=10,
 
193
                cores=20,
 
194
                ram=50 * 1024,
 
195
                volumes=10,
 
196
                gigabytes=1000,
 
197
                floating_ips=10,
 
198
                security_groups=10,
 
199
                security_group_rules=20,
 
200
                key_pairs=10,
 
201
                metadata_items=128,
 
202
                injected_files=5,
 
203
                injected_file_content_bytes=10 * 1024,
 
204
                ))
 
205
 
 
206
    def test_project_quotas_overrides_noclass(self):
 
207
        self._stub_class()
 
208
        self._stub_project(True)
 
209
        result = quota.get_project_quotas(self.context, 'admin')
 
210
        self.assertEqual(result, dict(
 
211
                instances=2,
 
212
                cores=5,
 
213
                ram=12 * 1024,
 
214
                volumes=2,
 
215
                gigabytes=250,
 
216
                floating_ips=2,
 
217
                security_groups=5,
 
218
                security_group_rules=10,
 
219
                key_pairs=5,
 
220
                metadata_items=32,
 
221
                injected_files=1,
 
222
                injected_file_content_bytes=2 * 1024,
 
223
                ))
 
224
 
 
225
    def test_project_quotas_defaults_withclass(self):
 
226
        self._stub_class()
 
227
        self._stub_project()
 
228
        self.context.quota_class = 'test_class'
 
229
        result = quota.get_project_quotas(self.context, 'admin')
 
230
        self.assertEqual(result, dict(
 
231
                instances=5,
 
232
                cores=10,
 
233
                ram=25 * 1024,
 
234
                volumes=5,
 
235
                gigabytes=500,
 
236
                floating_ips=5,
 
237
                security_groups=10,
 
238
                security_group_rules=20,
 
239
                key_pairs=10,
 
240
                metadata_items=64,
 
241
                injected_files=2,
 
242
                injected_file_content_bytes=5 * 1024,
 
243
                ))
 
244
 
 
245
    def test_project_quotas_overrides_withclass(self):
 
246
        self._stub_class()
 
247
        self._stub_project(True)
 
248
        self.context.quota_class = 'test_class'
 
249
        result = quota.get_project_quotas(self.context, 'admin')
 
250
        self.assertEqual(result, dict(
 
251
                instances=2,
 
252
                cores=5,
 
253
                ram=12 * 1024,
 
254
                volumes=2,
 
255
                gigabytes=250,
 
256
                floating_ips=2,
 
257
                security_groups=5,
 
258
                security_group_rules=10,
 
259
                key_pairs=5,
 
260
                metadata_items=32,
 
261
                injected_files=1,
 
262
                injected_file_content_bytes=2 * 1024,
 
263
                ))
 
264
 
 
265
 
 
266
class OldQuotaTestCase(test.TestCase):
36
267
 
37
268
    class StubImageService(object):
38
269
 
40
271
            return {"properties": {}}
41
272
 
42
273
    def setUp(self):
43
 
        super(QuotaTestCase, self).setUp()
 
274
        super(OldQuotaTestCase, self).setUp()
44
275
        self.flags(connection_type='fake',
45
276
                   quota_instances=2,
46
277
                   quota_cores=4,
49
280
                   quota_floating_ips=1,
50
281
                   network_manager='nova.network.manager.FlatDHCPManager')
51
282
 
52
 
        self.network = self.network = self.start_service('network')
 
283
        # Apparently needed by the RPC tests...
 
284
        self.network = self.start_service('network')
 
285
 
53
286
        self.user_id = 'admin'
54
287
        self.project_id = 'admin'
55
288
        self.context = context.RequestContext(self.user_id,
57
290
                                              is_admin=True)
58
291
        orig_rpc_call = rpc.call
59
292
 
60
 
        def rpc_call_wrapper(context, topic, msg):
 
293
        def rpc_call_wrapper(context, topic, msg, timeout=None):
61
294
            """Stub out the scheduler creating the instance entry"""
62
295
            if (topic == FLAGS.scheduler_topic and
63
296
                msg['method'] == 'run_instance'):
148
381
        num_instances = quota.allowed_instances(self.context, 100,
149
382
                                                instance_type)
150
383
        self.assertEqual(num_instances, 2)
151
 
        db.quota_create(self.context, self.project_id, 'instances', None)
152
 
        num_instances = quota.allowed_instances(self.context, 100,
153
 
                                                instance_type)
154
 
        self.assertEqual(num_instances, 100)
155
384
        db.quota_create(self.context, self.project_id, 'instances', -1)
156
385
        num_instances = quota.allowed_instances(self.context, 100,
157
386
                                                instance_type)
166
395
        num_instances = quota.allowed_instances(self.context, 100,
167
396
                                                instance_type)
168
397
        self.assertEqual(num_instances, 2)
169
 
        db.quota_create(self.context, self.project_id, 'ram', None)
170
 
        num_instances = quota.allowed_instances(self.context, 100,
171
 
                                                instance_type)
172
 
        self.assertEqual(num_instances, 100)
173
398
        db.quota_create(self.context, self.project_id, 'ram', -1)
174
399
        num_instances = quota.allowed_instances(self.context, 100,
175
400
                                                instance_type)
184
409
        num_instances = quota.allowed_instances(self.context, 100,
185
410
                                                instance_type)
186
411
        self.assertEqual(num_instances, 2)
187
 
        db.quota_create(self.context, self.project_id, 'cores', None)
188
 
        num_instances = quota.allowed_instances(self.context, 100,
189
 
                                                instance_type)
190
 
        self.assertEqual(num_instances, 100)
191
412
        db.quota_create(self.context, self.project_id, 'cores', -1)
192
413
        num_instances = quota.allowed_instances(self.context, 100,
193
414
                                                instance_type)
200
421
        self.flags(quota_volumes=10, quota_gigabytes=-1)
201
422
        volumes = quota.allowed_volumes(self.context, 100, 1)
202
423
        self.assertEqual(volumes, 10)
203
 
        db.quota_create(self.context, self.project_id, 'volumes', None)
204
 
        volumes = quota.allowed_volumes(self.context, 100, 1)
205
 
        self.assertEqual(volumes, 100)
206
424
        db.quota_create(self.context, self.project_id, 'volumes', -1)
207
425
        volumes = quota.allowed_volumes(self.context, 100, 1)
208
426
        self.assertEqual(volumes, 100)
213
431
        self.flags(quota_volumes=-1, quota_gigabytes=10)
214
432
        volumes = quota.allowed_volumes(self.context, 100, 1)
215
433
        self.assertEqual(volumes, 10)
216
 
        db.quota_create(self.context, self.project_id, 'gigabytes', None)
217
 
        volumes = quota.allowed_volumes(self.context, 100, 1)
218
 
        self.assertEqual(volumes, 100)
219
434
        db.quota_create(self.context, self.project_id, 'gigabytes', -1)
220
435
        volumes = quota.allowed_volumes(self.context, 100, 1)
221
436
        self.assertEqual(volumes, 100)
226
441
        self.flags(quota_floating_ips=10)
227
442
        floating_ips = quota.allowed_floating_ips(self.context, 100)
228
443
        self.assertEqual(floating_ips, 10)
229
 
        db.quota_create(self.context, self.project_id, 'floating_ips', None)
230
 
        floating_ips = quota.allowed_floating_ips(self.context, 100)
231
 
        self.assertEqual(floating_ips, 100)
232
444
        db.quota_create(self.context, self.project_id, 'floating_ips', -1)
233
445
        floating_ips = quota.allowed_floating_ips(self.context, 100)
234
446
        self.assertEqual(floating_ips, 100)
239
451
        self.flags(quota_security_groups=10)
240
452
        security_groups = quota.allowed_security_groups(self.context, 100)
241
453
        self.assertEqual(security_groups, 10)
242
 
        db.quota_create(self.context, self.project_id, 'security_groups', None)
 
454
        db.quota_create(self.context, self.project_id, 'security_groups', -1)
243
455
        security_groups = quota.allowed_security_groups(self.context, 100)
244
456
        self.assertEqual(security_groups, 100)
245
457
        security_groups = quota.allowed_security_groups(self.context, 101)
246
458
        self.assertEqual(security_groups, 101)
247
459
 
 
460
    def test_unlimited_key_pairs(self):
 
461
        self.flags(quota_key_pairs=10)
 
462
        key_pairs = quota.allowed_key_pairs(self.context, 100)
 
463
        self.assertEqual(key_pairs, 10)
 
464
        db.quota_create(self.context, self.project_id, 'key_pairs', -1)
 
465
        key_pairs = quota.allowed_key_pairs(self.context, 100)
 
466
        self.assertEqual(key_pairs, 100)
 
467
        key_pairs = quota.allowed_key_pairs(self.context, 101)
 
468
        self.assertEqual(key_pairs, 101)
 
469
 
248
470
    def test_unlimited_security_group_rules(self):
249
471
 
250
472
        def fake_security_group_rule_count_by_group(context, sec_group_id):
257
479
        rules = quota.allowed_security_group_rules(self.context, 1234, 100)
258
480
        self.assertEqual(rules, 20)
259
481
        db.quota_create(self.context, self.project_id, 'security_group_rules',
260
 
                        None)
 
482
                        -1)
261
483
        rules = quota.allowed_security_group_rules(self.context, 1234, 100)
262
484
        self.assertEqual(rules, 100)
263
485
        rules = quota.allowed_security_group_rules(self.context, 1234, 101)
267
489
        self.flags(quota_metadata_items=10)
268
490
        items = quota.allowed_metadata_items(self.context, 100)
269
491
        self.assertEqual(items, 10)
270
 
        db.quota_create(self.context, self.project_id, 'metadata_items', None)
271
 
        items = quota.allowed_metadata_items(self.context, 100)
272
 
        self.assertEqual(items, 100)
273
492
        db.quota_create(self.context, self.project_id, 'metadata_items', -1)
274
493
        items = quota.allowed_metadata_items(self.context, 100)
275
494
        self.assertEqual(items, 100)
354
573
                                            metadata=metadata)
355
574
 
356
575
    def test_default_allowed_injected_files(self):
357
 
        self.flags(quota_max_injected_files=55)
 
576
        self.flags(quota_injected_files=55)
358
577
        self.assertEqual(quota.allowed_injected_files(self.context, 100), 55)
359
578
 
360
579
    def test_overridden_allowed_injected_files(self):
361
 
        self.flags(quota_max_injected_files=5)
 
580
        self.flags(quota_injected_files=5)
362
581
        db.quota_create(self.context, self.project_id, 'injected_files', 77)
363
582
        self.assertEqual(quota.allowed_injected_files(self.context, 100), 77)
364
583
 
365
584
    def test_unlimited_default_allowed_injected_files(self):
366
 
        self.flags(quota_max_injected_files=-1)
 
585
        self.flags(quota_injected_files=-1)
367
586
        self.assertEqual(quota.allowed_injected_files(self.context, 100), 100)
368
587
 
369
588
    def test_unlimited_db_allowed_injected_files(self):
370
 
        self.flags(quota_max_injected_files=5)
371
 
        db.quota_create(self.context, self.project_id, 'injected_files', None)
 
589
        self.flags(quota_injected_files=5)
 
590
        db.quota_create(self.context, self.project_id, 'injected_files', -1)
372
591
        self.assertEqual(quota.allowed_injected_files(self.context, 100), 100)
373
592
 
374
593
    def test_default_allowed_injected_file_content_bytes(self):
375
 
        self.flags(quota_max_injected_file_content_bytes=12345)
 
594
        self.flags(quota_injected_file_content_bytes=12345)
376
595
        limit = quota.allowed_injected_file_content_bytes(self.context, 23456)
377
596
        self.assertEqual(limit, 12345)
378
597
 
379
598
    def test_overridden_allowed_injected_file_content_bytes(self):
380
 
        self.flags(quota_max_injected_file_content_bytes=12345)
 
599
        self.flags(quota_injected_file_content_bytes=12345)
381
600
        db.quota_create(self.context, self.project_id,
382
601
                        'injected_file_content_bytes', 5678)
383
602
        limit = quota.allowed_injected_file_content_bytes(self.context, 23456)
384
603
        self.assertEqual(limit, 5678)
385
604
 
386
605
    def test_unlimited_default_allowed_injected_file_content_bytes(self):
387
 
        self.flags(quota_max_injected_file_content_bytes=-1)
 
606
        self.flags(quota_injected_file_content_bytes=-1)
388
607
        limit = quota.allowed_injected_file_content_bytes(self.context, 23456)
389
608
        self.assertEqual(limit, 23456)
390
609
 
391
610
    def test_unlimited_db_allowed_injected_file_content_bytes(self):
392
 
        self.flags(quota_max_injected_file_content_bytes=12345)
 
611
        self.flags(quota_injected_file_content_bytes=12345)
393
612
        db.quota_create(self.context, self.project_id,
394
 
                        'injected_file_content_bytes', None)
 
613
                        'injected_file_content_bytes', -1)
395
614
        limit = quota.allowed_injected_file_content_bytes(self.context, 23456)
396
615
        self.assertEqual(limit, 23456)
397
616
 
415
634
 
416
635
    def test_max_injected_files(self):
417
636
        files = []
418
 
        for i in xrange(FLAGS.quota_max_injected_files):
 
637
        for i in xrange(FLAGS.quota_injected_files):
419
638
            files.append(('/my/path%d' % i, 'config = test\n'))
420
639
        self._create_with_injected_files(files)  # no QuotaError
421
640
 
422
641
    def test_too_many_injected_files(self):
423
642
        files = []
424
 
        for i in xrange(FLAGS.quota_max_injected_files + 1):
 
643
        for i in xrange(FLAGS.quota_injected_files + 1):
425
644
            files.append(('/my/path%d' % i, 'my\ncontent%d\n' % i))
426
645
        self.assertRaises(exception.QuotaError,
427
646
                          self._create_with_injected_files, files)
428
647
 
429
648
    def test_max_injected_file_content_bytes(self):
430
 
        max = FLAGS.quota_max_injected_file_content_bytes
 
649
        max = FLAGS.quota_injected_file_content_bytes
431
650
        content = ''.join(['a' for i in xrange(max)])
432
651
        files = [('/test/path', content)]
433
652
        self._create_with_injected_files(files)  # no QuotaError
434
653
 
435
654
    def test_too_many_injected_file_content_bytes(self):
436
 
        max = FLAGS.quota_max_injected_file_content_bytes
 
655
        max = FLAGS.quota_injected_file_content_bytes
437
656
        content = ''.join(['a' for i in xrange(max + 1)])
438
657
        files = [('/test/path', content)]
439
658
        self.assertRaises(exception.QuotaError,
442
661
    def test_allowed_injected_file_path_bytes(self):
443
662
        self.assertEqual(
444
663
                quota.allowed_injected_file_path_bytes(self.context),
445
 
                FLAGS.quota_max_injected_file_path_bytes)
 
664
                FLAGS.quota_injected_file_path_bytes)
446
665
 
447
666
    def test_max_injected_file_path_bytes(self):
448
 
        max = FLAGS.quota_max_injected_file_path_bytes
 
667
        max = FLAGS.quota_injected_file_path_bytes
449
668
        path = ''.join(['a' for i in xrange(max)])
450
669
        files = [(path, 'config = quotatest')]
451
670
        self._create_with_injected_files(files)  # no QuotaError
452
671
 
453
672
    def test_too_many_injected_file_path_bytes(self):
454
 
        max = FLAGS.quota_max_injected_file_path_bytes
 
673
        max = FLAGS.quota_injected_file_path_bytes
455
674
        path = ''.join(['a' for i in xrange(max + 1)])
456
675
        files = [(path, 'config = quotatest')]
457
676
        self.assertRaises(exception.QuotaError,
458
677
                          self._create_with_injected_files, files)
 
678
 
 
679
    def test_quota_class_unlimited(self):
 
680
        self.flags(quota_floating_ips=10)
 
681
        items = quota.allowed_floating_ips(self.context, 10)
 
682
        self.assertEqual(items, 10)
 
683
        self.context.quota_class = 'foo'
 
684
        db.quota_class_create(self.context, 'foo', 'floating_ips', -1)
 
685
        items = quota.allowed_floating_ips(self.context, 100)
 
686
        self.assertEqual(items, 100)
 
687
 
 
688
 
 
689
class FakeContext(object):
 
690
    def __init__(self, project_id, quota_class):
 
691
        self.is_admin = False
 
692
        self.user_id = 'fake_user'
 
693
        self.project_id = project_id
 
694
        self.quota_class = quota_class
 
695
 
 
696
    def elevated(self):
 
697
        elevated = self.__class__(self.project_id, self.quota_class)
 
698
        elevated.is_admin = True
 
699
        return elevated
 
700
 
 
701
 
 
702
class FakeDriver(object):
 
703
    def __init__(self, by_project=None, by_class=None, reservations=None):
 
704
        self.called = []
 
705
        self.by_project = by_project or {}
 
706
        self.by_class = by_class or {}
 
707
        self.reservations = reservations or []
 
708
 
 
709
    def get_by_project(self, context, project_id, resource):
 
710
        self.called.append(('get_by_project', context, project_id, resource))
 
711
        try:
 
712
            return self.by_project[project_id][resource]
 
713
        except KeyError:
 
714
            raise exception.ProjectQuotaNotFound(project_id=project_id)
 
715
 
 
716
    def get_by_class(self, context, quota_class, resource):
 
717
        self.called.append(('get_by_class', context, quota_class, resource))
 
718
        try:
 
719
            return self.by_class[quota_class][resource]
 
720
        except KeyError:
 
721
            raise exception.QuotaClassNotFound(class_name=quota_class)
 
722
 
 
723
    def get_defaults(self, context, resources):
 
724
        self.called.append(('get_defaults', context, resources))
 
725
        return resources
 
726
 
 
727
    def get_class_quotas(self, context, resources, quota_class,
 
728
                         defaults=True):
 
729
        self.called.append(('get_class_quotas', context, resources,
 
730
                            quota_class, defaults))
 
731
        return resources
 
732
 
 
733
    def get_project_quotas(self, context, resources, project_id,
 
734
                           quota_class=None, defaults=True, usages=True):
 
735
        self.called.append(('get_project_quotas', context, resources,
 
736
                            project_id, quota_class, defaults, usages))
 
737
        return resources
 
738
 
 
739
    def limit_check(self, context, resources, values):
 
740
        self.called.append(('limit_check', context, resources, values))
 
741
 
 
742
    def reserve(self, context, resources, deltas, expire=None):
 
743
        self.called.append(('reserve', context, resources, deltas, expire))
 
744
        return self.reservations
 
745
 
 
746
    def commit(self, context, reservations):
 
747
        self.called.append(('commit', context, reservations))
 
748
 
 
749
    def rollback(self, context, reservations):
 
750
        self.called.append(('rollback', context, reservations))
 
751
 
 
752
    def destroy_all_by_project(self, context, project_id):
 
753
        self.called.append(('destroy_all_by_project', context, project_id))
 
754
 
 
755
    def expire(self, context):
 
756
        self.called.append(('expire', context))
 
757
 
 
758
 
 
759
class BaseResourceTestCase(test.TestCase):
 
760
    def test_no_flag(self):
 
761
        resource = quota.BaseResource('test_resource')
 
762
 
 
763
        self.assertEqual(resource.name, 'test_resource')
 
764
        self.assertEqual(resource.flag, None)
 
765
        self.assertEqual(resource.default, -1)
 
766
 
 
767
    def test_with_flag(self):
 
768
        # We know this flag exists, so use it...
 
769
        self.flags(quota_instances=10)
 
770
        resource = quota.BaseResource('test_resource', 'quota_instances')
 
771
 
 
772
        self.assertEqual(resource.name, 'test_resource')
 
773
        self.assertEqual(resource.flag, 'quota_instances')
 
774
        self.assertEqual(resource.default, 10)
 
775
 
 
776
    def test_with_flag_no_quota(self):
 
777
        self.flags(quota_instances=-1)
 
778
        resource = quota.BaseResource('test_resource', 'quota_instances')
 
779
 
 
780
        self.assertEqual(resource.name, 'test_resource')
 
781
        self.assertEqual(resource.flag, 'quota_instances')
 
782
        self.assertEqual(resource.default, -1)
 
783
 
 
784
    def test_quota_no_project_no_class(self):
 
785
        self.flags(quota_instances=10)
 
786
        resource = quota.BaseResource('test_resource', 'quota_instances')
 
787
        driver = FakeDriver()
 
788
        context = FakeContext(None, None)
 
789
        quota_value = resource.quota(driver, context)
 
790
 
 
791
        self.assertEqual(quota_value, 10)
 
792
 
 
793
    def test_quota_with_project_no_class(self):
 
794
        self.flags(quota_instances=10)
 
795
        resource = quota.BaseResource('test_resource', 'quota_instances')
 
796
        driver = FakeDriver(by_project=dict(
 
797
                test_project=dict(test_resource=15),
 
798
                ))
 
799
        context = FakeContext('test_project', None)
 
800
        quota_value = resource.quota(driver, context)
 
801
 
 
802
        self.assertEqual(quota_value, 15)
 
803
 
 
804
    def test_quota_no_project_with_class(self):
 
805
        self.flags(quota_instances=10)
 
806
        resource = quota.BaseResource('test_resource', 'quota_instances')
 
807
        driver = FakeDriver(by_class=dict(
 
808
                test_class=dict(test_resource=20),
 
809
                ))
 
810
        context = FakeContext(None, 'test_class')
 
811
        quota_value = resource.quota(driver, context)
 
812
 
 
813
        self.assertEqual(quota_value, 20)
 
814
 
 
815
    def test_quota_with_project_with_class(self):
 
816
        self.flags(quota_instances=10)
 
817
        resource = quota.BaseResource('test_resource', 'quota_instances')
 
818
        driver = FakeDriver(by_project=dict(
 
819
                test_project=dict(test_resource=15),
 
820
                ),
 
821
                            by_class=dict(
 
822
                test_class=dict(test_resource=20),
 
823
                ))
 
824
        context = FakeContext('test_project', 'test_class')
 
825
        quota_value = resource.quota(driver, context)
 
826
 
 
827
        self.assertEqual(quota_value, 15)
 
828
 
 
829
    def test_quota_override_project_with_class(self):
 
830
        self.flags(quota_instances=10)
 
831
        resource = quota.BaseResource('test_resource', 'quota_instances')
 
832
        driver = FakeDriver(by_project=dict(
 
833
                test_project=dict(test_resource=15),
 
834
                override_project=dict(test_resource=20),
 
835
                ))
 
836
        context = FakeContext('test_project', 'test_class')
 
837
        quota_value = resource.quota(driver, context,
 
838
                                     project_id='override_project')
 
839
 
 
840
        self.assertEqual(quota_value, 20)
 
841
 
 
842
    def test_quota_with_project_override_class(self):
 
843
        self.flags(quota_instances=10)
 
844
        resource = quota.BaseResource('test_resource', 'quota_instances')
 
845
        driver = FakeDriver(by_class=dict(
 
846
                test_class=dict(test_resource=15),
 
847
                override_class=dict(test_resource=20),
 
848
                ))
 
849
        context = FakeContext('test_project', 'test_class')
 
850
        quota_value = resource.quota(driver, context,
 
851
                                     quota_class='override_class')
 
852
 
 
853
        self.assertEqual(quota_value, 20)
 
854
 
 
855
 
 
856
class QuotaEngineTestCase(test.TestCase):
 
857
    def test_init(self):
 
858
        quota_obj = quota.QuotaEngine()
 
859
 
 
860
        self.assertEqual(quota_obj._resources, {})
 
861
        self.assertTrue(isinstance(quota_obj._driver, quota.DbQuotaDriver))
 
862
 
 
863
    def test_init_override_string(self):
 
864
        quota_obj = quota.QuotaEngine(
 
865
            quota_driver_class='nova.tests.test_quota.FakeDriver')
 
866
 
 
867
        self.assertEqual(quota_obj._resources, {})
 
868
        self.assertTrue(isinstance(quota_obj._driver, FakeDriver))
 
869
 
 
870
    def test_init_override_obj(self):
 
871
        quota_obj = quota.QuotaEngine(quota_driver_class=FakeDriver)
 
872
 
 
873
        self.assertEqual(quota_obj._resources, {})
 
874
        self.assertEqual(quota_obj._driver, FakeDriver)
 
875
 
 
876
    def test_register_resource(self):
 
877
        quota_obj = quota.QuotaEngine()
 
878
        resource = quota.AbsoluteResource('test_resource')
 
879
        quota_obj.register_resource(resource)
 
880
 
 
881
        self.assertEqual(quota_obj._resources, dict(test_resource=resource))
 
882
 
 
883
    def test_register_resources(self):
 
884
        quota_obj = quota.QuotaEngine()
 
885
        resources = [
 
886
            quota.AbsoluteResource('test_resource1'),
 
887
            quota.AbsoluteResource('test_resource2'),
 
888
            quota.AbsoluteResource('test_resource3'),
 
889
            ]
 
890
        quota_obj.register_resources(resources)
 
891
 
 
892
        self.assertEqual(quota_obj._resources, dict(
 
893
                test_resource1=resources[0],
 
894
                test_resource2=resources[1],
 
895
                test_resource3=resources[2],
 
896
                ))
 
897
 
 
898
    def test_sync_predeclared(self):
 
899
        quota_obj = quota.QuotaEngine()
 
900
 
 
901
        def spam(*args, **kwargs):
 
902
            pass
 
903
 
 
904
        resource = quota.ReservableResource('test_resource', spam)
 
905
        quota_obj.register_resource(resource)
 
906
 
 
907
        self.assertEqual(resource.sync, spam)
 
908
 
 
909
    def test_sync_multi(self):
 
910
        quota_obj = quota.QuotaEngine()
 
911
 
 
912
        def spam(*args, **kwargs):
 
913
            pass
 
914
 
 
915
        resources = [
 
916
            quota.ReservableResource('test_resource1', spam),
 
917
            quota.ReservableResource('test_resource2', spam),
 
918
            quota.ReservableResource('test_resource3', spam),
 
919
            quota.ReservableResource('test_resource4', spam),
 
920
            ]
 
921
        quota_obj.register_resources(resources[:2])
 
922
 
 
923
        self.assertEqual(resources[0].sync, spam)
 
924
        self.assertEqual(resources[1].sync, spam)
 
925
        self.assertEqual(resources[2].sync, spam)
 
926
        self.assertEqual(resources[3].sync, spam)
 
927
 
 
928
    def test_get_by_project(self):
 
929
        context = FakeContext('test_project', 'test_class')
 
930
        driver = FakeDriver(by_project=dict(
 
931
                test_project=dict(test_resource=42)))
 
932
        quota_obj = quota.QuotaEngine(quota_driver_class=driver)
 
933
        result = quota_obj.get_by_project(context, 'test_project',
 
934
                                          'test_resource')
 
935
 
 
936
        self.assertEqual(driver.called, [
 
937
                ('get_by_project', context, 'test_project', 'test_resource'),
 
938
                ])
 
939
        self.assertEqual(result, 42)
 
940
 
 
941
    def test_get_by_class(self):
 
942
        context = FakeContext('test_project', 'test_class')
 
943
        driver = FakeDriver(by_class=dict(
 
944
                test_class=dict(test_resource=42)))
 
945
        quota_obj = quota.QuotaEngine(quota_driver_class=driver)
 
946
        result = quota_obj.get_by_class(context, 'test_class', 'test_resource')
 
947
 
 
948
        self.assertEqual(driver.called, [
 
949
                ('get_by_class', context, 'test_class', 'test_resource'),
 
950
                ])
 
951
        self.assertEqual(result, 42)
 
952
 
 
953
    def _make_quota_obj(self, driver):
 
954
        quota_obj = quota.QuotaEngine(quota_driver_class=driver)
 
955
        resources = [
 
956
            quota.AbsoluteResource('test_resource4'),
 
957
            quota.AbsoluteResource('test_resource3'),
 
958
            quota.AbsoluteResource('test_resource2'),
 
959
            quota.AbsoluteResource('test_resource1'),
 
960
            ]
 
961
        quota_obj.register_resources(resources)
 
962
 
 
963
        return quota_obj
 
964
 
 
965
    def test_get_defaults(self):
 
966
        context = FakeContext(None, None)
 
967
        driver = FakeDriver()
 
968
        quota_obj = self._make_quota_obj(driver)
 
969
        result = quota_obj.get_defaults(context)
 
970
 
 
971
        self.assertEqual(driver.called, [
 
972
                ('get_defaults', context, quota_obj._resources),
 
973
                ])
 
974
        self.assertEqual(result, quota_obj._resources)
 
975
 
 
976
    def test_get_class_quotas(self):
 
977
        context = FakeContext(None, None)
 
978
        driver = FakeDriver()
 
979
        quota_obj = self._make_quota_obj(driver)
 
980
        result1 = quota_obj.get_class_quotas(context, 'test_class')
 
981
        result2 = quota_obj.get_class_quotas(context, 'test_class', False)
 
982
 
 
983
        self.assertEqual(driver.called, [
 
984
                ('get_class_quotas', context, quota_obj._resources,
 
985
                 'test_class', True),
 
986
                ('get_class_quotas', context, quota_obj._resources,
 
987
                 'test_class', False),
 
988
                ])
 
989
        self.assertEqual(result1, quota_obj._resources)
 
990
        self.assertEqual(result2, quota_obj._resources)
 
991
 
 
992
    def test_get_project_quotas(self):
 
993
        context = FakeContext(None, None)
 
994
        driver = FakeDriver()
 
995
        quota_obj = self._make_quota_obj(driver)
 
996
        result1 = quota_obj.get_project_quotas(context, 'test_project')
 
997
        result2 = quota_obj.get_project_quotas(context, 'test_project',
 
998
                                               quota_class='test_class',
 
999
                                               defaults=False,
 
1000
                                               usages=False)
 
1001
 
 
1002
        self.assertEqual(driver.called, [
 
1003
                ('get_project_quotas', context, quota_obj._resources,
 
1004
                 'test_project', None, True, True),
 
1005
                ('get_project_quotas', context, quota_obj._resources,
 
1006
                 'test_project', 'test_class', False, False),
 
1007
                ])
 
1008
        self.assertEqual(result1, quota_obj._resources)
 
1009
        self.assertEqual(result2, quota_obj._resources)
 
1010
 
 
1011
    def test_count_no_resource(self):
 
1012
        context = FakeContext(None, None)
 
1013
        driver = FakeDriver()
 
1014
        quota_obj = self._make_quota_obj(driver)
 
1015
        self.assertRaises(exception.QuotaResourceUnknown,
 
1016
                          quota_obj.count, context, 'test_resource5',
 
1017
                          True, foo='bar')
 
1018
 
 
1019
    def test_count_wrong_resource(self):
 
1020
        context = FakeContext(None, None)
 
1021
        driver = FakeDriver()
 
1022
        quota_obj = self._make_quota_obj(driver)
 
1023
        self.assertRaises(exception.QuotaResourceUnknown,
 
1024
                          quota_obj.count, context, 'test_resource1',
 
1025
                          True, foo='bar')
 
1026
 
 
1027
    def test_count(self):
 
1028
        def fake_count(context, *args, **kwargs):
 
1029
            self.assertEqual(args, (True,))
 
1030
            self.assertEqual(kwargs, dict(foo='bar'))
 
1031
            return 5
 
1032
 
 
1033
        context = FakeContext(None, None)
 
1034
        driver = FakeDriver()
 
1035
        quota_obj = self._make_quota_obj(driver)
 
1036
        quota_obj.register_resource(quota.CountableResource('test_resource5',
 
1037
                                                            fake_count))
 
1038
        result = quota_obj.count(context, 'test_resource5', True, foo='bar')
 
1039
 
 
1040
        self.assertEqual(result, 5)
 
1041
 
 
1042
    def test_limit_check(self):
 
1043
        context = FakeContext(None, None)
 
1044
        driver = FakeDriver()
 
1045
        quota_obj = self._make_quota_obj(driver)
 
1046
        quota_obj.limit_check(context, test_resource1=4, test_resource2=3,
 
1047
                              test_resource3=2, test_resource4=1)
 
1048
 
 
1049
        self.assertEqual(driver.called, [
 
1050
                ('limit_check', context, quota_obj._resources, dict(
 
1051
                        test_resource1=4,
 
1052
                        test_resource2=3,
 
1053
                        test_resource3=2,
 
1054
                        test_resource4=1,
 
1055
                        )),
 
1056
                ])
 
1057
 
 
1058
    def test_reserve(self):
 
1059
        context = FakeContext(None, None)
 
1060
        driver = FakeDriver(reservations=[
 
1061
                'resv-01', 'resv-02', 'resv-03', 'resv-04',
 
1062
                ])
 
1063
        quota_obj = self._make_quota_obj(driver)
 
1064
        result1 = quota_obj.reserve(context, test_resource1=4,
 
1065
                                    test_resource2=3, test_resource3=2,
 
1066
                                    test_resource4=1)
 
1067
        result2 = quota_obj.reserve(context, expire=3600,
 
1068
                                    test_resource1=1, test_resource2=2,
 
1069
                                    test_resource3=3, test_resource4=4)
 
1070
 
 
1071
        self.assertEqual(driver.called, [
 
1072
                ('reserve', context, quota_obj._resources, dict(
 
1073
                        test_resource1=4,
 
1074
                        test_resource2=3,
 
1075
                        test_resource3=2,
 
1076
                        test_resource4=1,
 
1077
                        ), None),
 
1078
                ('reserve', context, quota_obj._resources, dict(
 
1079
                        test_resource1=1,
 
1080
                        test_resource2=2,
 
1081
                        test_resource3=3,
 
1082
                        test_resource4=4,
 
1083
                        ), 3600),
 
1084
                ])
 
1085
        self.assertEqual(result1, [
 
1086
                'resv-01', 'resv-02', 'resv-03', 'resv-04',
 
1087
                ])
 
1088
        self.assertEqual(result2, [
 
1089
                'resv-01', 'resv-02', 'resv-03', 'resv-04',
 
1090
                ])
 
1091
 
 
1092
    def test_commit(self):
 
1093
        context = FakeContext(None, None)
 
1094
        driver = FakeDriver()
 
1095
        quota_obj = self._make_quota_obj(driver)
 
1096
        quota_obj.commit(context, ['resv-01', 'resv-02', 'resv-03'])
 
1097
 
 
1098
        self.assertEqual(driver.called, [
 
1099
                ('commit', context, ['resv-01', 'resv-02', 'resv-03']),
 
1100
                ])
 
1101
 
 
1102
    def test_rollback(self):
 
1103
        context = FakeContext(None, None)
 
1104
        driver = FakeDriver()
 
1105
        quota_obj = self._make_quota_obj(driver)
 
1106
        quota_obj.rollback(context, ['resv-01', 'resv-02', 'resv-03'])
 
1107
 
 
1108
        self.assertEqual(driver.called, [
 
1109
                ('rollback', context, ['resv-01', 'resv-02', 'resv-03']),
 
1110
                ])
 
1111
 
 
1112
    def test_destroy_all_by_project(self):
 
1113
        context = FakeContext(None, None)
 
1114
        driver = FakeDriver()
 
1115
        quota_obj = self._make_quota_obj(driver)
 
1116
        quota_obj.destroy_all_by_project(context, 'test_project')
 
1117
 
 
1118
        self.assertEqual(driver.called, [
 
1119
                ('destroy_all_by_project', context, 'test_project'),
 
1120
                ])
 
1121
 
 
1122
    def test_expire(self):
 
1123
        context = FakeContext(None, None)
 
1124
        driver = FakeDriver()
 
1125
        quota_obj = self._make_quota_obj(driver)
 
1126
        quota_obj.expire(context)
 
1127
 
 
1128
        self.assertEqual(driver.called, [
 
1129
                ('expire', context),
 
1130
                ])
 
1131
 
 
1132
    def test_resources(self):
 
1133
        quota_obj = self._make_quota_obj(None)
 
1134
 
 
1135
        self.assertEqual(quota_obj.resources,
 
1136
                         ['test_resource1', 'test_resource2',
 
1137
                          'test_resource3', 'test_resource4'])
 
1138
 
 
1139
 
 
1140
class DbQuotaDriverTestCase(test.TestCase):
 
1141
    def setUp(self):
 
1142
        super(DbQuotaDriverTestCase, self).setUp()
 
1143
 
 
1144
        self.flags(quota_instances=10,
 
1145
                   quota_cores=20,
 
1146
                   quota_ram=50 * 1024,
 
1147
                   quota_volumes=10,
 
1148
                   quota_gigabytes=1000,
 
1149
                   quota_floating_ips=10,
 
1150
                   quota_metadata_items=128,
 
1151
                   quota_injected_files=5,
 
1152
                   quota_injected_file_content_bytes=10 * 1024,
 
1153
                   quota_injected_file_path_bytes=255,
 
1154
                   quota_security_groups=10,
 
1155
                   quota_security_group_rules=20,
 
1156
                   reservation_expire=86400,
 
1157
                   until_refresh=0,
 
1158
                   max_age=0,
 
1159
                   )
 
1160
 
 
1161
        self.driver = quota.DbQuotaDriver()
 
1162
 
 
1163
        self.calls = []
 
1164
 
 
1165
        utils.set_time_override()
 
1166
 
 
1167
    def tearDown(self):
 
1168
        utils.clear_time_override()
 
1169
        super(DbQuotaDriverTestCase, self).tearDown()
 
1170
 
 
1171
    def test_get_defaults(self):
 
1172
        # Use our pre-defined resources
 
1173
        result = self.driver.get_defaults(None, quota.QUOTAS._resources)
 
1174
 
 
1175
        self.assertEqual(result, dict(
 
1176
                instances=10,
 
1177
                cores=20,
 
1178
                ram=50 * 1024,
 
1179
                volumes=10,
 
1180
                gigabytes=1000,
 
1181
                floating_ips=10,
 
1182
                metadata_items=128,
 
1183
                injected_files=5,
 
1184
                injected_file_content_bytes=10 * 1024,
 
1185
                injected_file_path_bytes=255,
 
1186
                security_groups=10,
 
1187
                security_group_rules=20,
 
1188
                key_pairs=100,
 
1189
                ))
 
1190
 
 
1191
    def _stub_quota_class_get_all_by_name(self):
 
1192
        # Stub out quota_class_get_all_by_name
 
1193
        def fake_qcgabn(context, quota_class):
 
1194
            self.calls.append('quota_class_get_all_by_name')
 
1195
            self.assertEqual(quota_class, 'test_class')
 
1196
            return dict(
 
1197
                instances=5,
 
1198
                ram=25 * 1024,
 
1199
                gigabytes=500,
 
1200
                metadata_items=64,
 
1201
                injected_file_content_bytes=5 * 1024,
 
1202
                )
 
1203
        self.stubs.Set(db, 'quota_class_get_all_by_name', fake_qcgabn)
 
1204
 
 
1205
    def test_get_class_quotas(self):
 
1206
        self._stub_quota_class_get_all_by_name()
 
1207
        result = self.driver.get_class_quotas(None, quota.QUOTAS._resources,
 
1208
                                              'test_class')
 
1209
 
 
1210
        self.assertEqual(self.calls, ['quota_class_get_all_by_name'])
 
1211
        self.assertEqual(result, dict(
 
1212
                instances=5,
 
1213
                cores=20,
 
1214
                ram=25 * 1024,
 
1215
                volumes=10,
 
1216
                gigabytes=500,
 
1217
                floating_ips=10,
 
1218
                metadata_items=64,
 
1219
                injected_files=5,
 
1220
                injected_file_content_bytes=5 * 1024,
 
1221
                injected_file_path_bytes=255,
 
1222
                security_groups=10,
 
1223
                security_group_rules=20,
 
1224
                key_pairs=100,
 
1225
                ))
 
1226
 
 
1227
    def test_get_class_quotas_no_defaults(self):
 
1228
        self._stub_quota_class_get_all_by_name()
 
1229
        result = self.driver.get_class_quotas(None, quota.QUOTAS._resources,
 
1230
                                              'test_class', False)
 
1231
 
 
1232
        self.assertEqual(self.calls, ['quota_class_get_all_by_name'])
 
1233
        self.assertEqual(result, dict(
 
1234
                instances=5,
 
1235
                ram=25 * 1024,
 
1236
                gigabytes=500,
 
1237
                metadata_items=64,
 
1238
                injected_file_content_bytes=5 * 1024,
 
1239
                ))
 
1240
 
 
1241
    def _stub_get_by_project(self):
 
1242
        def fake_qgabp(context, project_id):
 
1243
            self.calls.append('quota_get_all_by_project')
 
1244
            self.assertEqual(project_id, 'test_project')
 
1245
            return dict(
 
1246
                cores=10,
 
1247
                gigabytes=50,
 
1248
                injected_files=2,
 
1249
                injected_file_path_bytes=127,
 
1250
                )
 
1251
 
 
1252
        def fake_qugabp(context, project_id):
 
1253
            self.calls.append('quota_usage_get_all_by_project')
 
1254
            self.assertEqual(project_id, 'test_project')
 
1255
            return dict(
 
1256
                instances=dict(in_use=2, reserved=2),
 
1257
                cores=dict(in_use=4, reserved=4),
 
1258
                ram=dict(in_use=10 * 1024, reserved=0),
 
1259
                volumes=dict(in_use=2, reserved=0),
 
1260
                gigabytes=dict(in_use=10, reserved=0),
 
1261
                floating_ips=dict(in_use=2, reserved=0),
 
1262
                metadata_items=dict(in_use=0, reserved=0),
 
1263
                injected_files=dict(in_use=0, reserved=0),
 
1264
                injected_file_content_bytes=dict(in_use=0, reserved=0),
 
1265
                injected_file_path_bytes=dict(in_use=0, reserved=0),
 
1266
                )
 
1267
 
 
1268
        self.stubs.Set(db, 'quota_get_all_by_project', fake_qgabp)
 
1269
        self.stubs.Set(db, 'quota_usage_get_all_by_project', fake_qugabp)
 
1270
 
 
1271
        self._stub_quota_class_get_all_by_name()
 
1272
 
 
1273
    def test_get_project_quotas(self):
 
1274
        self._stub_get_by_project()
 
1275
        result = self.driver.get_project_quotas(
 
1276
            FakeContext('test_project', 'test_class'),
 
1277
            quota.QUOTAS._resources, 'test_project')
 
1278
 
 
1279
        self.assertEqual(self.calls, [
 
1280
                'quota_get_all_by_project',
 
1281
                'quota_usage_get_all_by_project',
 
1282
                'quota_class_get_all_by_name',
 
1283
                ])
 
1284
        self.assertEqual(result, dict(
 
1285
                instances=dict(
 
1286
                    limit=5,
 
1287
                    in_use=2,
 
1288
                    reserved=2,
 
1289
                    ),
 
1290
                cores=dict(
 
1291
                    limit=10,
 
1292
                    in_use=4,
 
1293
                    reserved=4,
 
1294
                    ),
 
1295
                ram=dict(
 
1296
                    limit=25 * 1024,
 
1297
                    in_use=10 * 1024,
 
1298
                    reserved=0,
 
1299
                    ),
 
1300
                volumes=dict(
 
1301
                    limit=10,
 
1302
                    in_use=2,
 
1303
                    reserved=0,
 
1304
                    ),
 
1305
                gigabytes=dict(
 
1306
                    limit=50,
 
1307
                    in_use=10,
 
1308
                    reserved=0,
 
1309
                    ),
 
1310
                floating_ips=dict(
 
1311
                    limit=10,
 
1312
                    in_use=2,
 
1313
                    reserved=0,
 
1314
                    ),
 
1315
                metadata_items=dict(
 
1316
                    limit=64,
 
1317
                    in_use=0,
 
1318
                    reserved=0,
 
1319
                    ),
 
1320
                injected_files=dict(
 
1321
                    limit=2,
 
1322
                    in_use=0,
 
1323
                    reserved=0,
 
1324
                    ),
 
1325
                injected_file_content_bytes=dict(
 
1326
                    limit=5 * 1024,
 
1327
                    in_use=0,
 
1328
                    reserved=0,
 
1329
                    ),
 
1330
                injected_file_path_bytes=dict(
 
1331
                    limit=127,
 
1332
                    in_use=0,
 
1333
                    reserved=0,
 
1334
                    ),
 
1335
                security_groups=dict(
 
1336
                    limit=10,
 
1337
                    in_use=0,
 
1338
                    reserved=0,
 
1339
                    ),
 
1340
                security_group_rules=dict(
 
1341
                    limit=20,
 
1342
                    in_use=0,
 
1343
                    reserved=0,
 
1344
                    ),
 
1345
                key_pairs=dict(
 
1346
                    limit=100,
 
1347
                    in_use=0,
 
1348
                    reserved=0,
 
1349
                    ),
 
1350
                ))
 
1351
 
 
1352
    def test_get_project_quotas_alt_context_no_class(self):
 
1353
        self._stub_get_by_project()
 
1354
        result = self.driver.get_project_quotas(
 
1355
            FakeContext('other_project', 'other_class'),
 
1356
            quota.QUOTAS._resources, 'test_project')
 
1357
 
 
1358
        self.assertEqual(self.calls, [
 
1359
                'quota_get_all_by_project',
 
1360
                'quota_usage_get_all_by_project',
 
1361
                ])
 
1362
        self.assertEqual(result, dict(
 
1363
                instances=dict(
 
1364
                    limit=10,
 
1365
                    in_use=2,
 
1366
                    reserved=2,
 
1367
                    ),
 
1368
                cores=dict(
 
1369
                    limit=10,
 
1370
                    in_use=4,
 
1371
                    reserved=4,
 
1372
                    ),
 
1373
                ram=dict(
 
1374
                    limit=50 * 1024,
 
1375
                    in_use=10 * 1024,
 
1376
                    reserved=0,
 
1377
                    ),
 
1378
                volumes=dict(
 
1379
                    limit=10,
 
1380
                    in_use=2,
 
1381
                    reserved=0,
 
1382
                    ),
 
1383
                gigabytes=dict(
 
1384
                    limit=50,
 
1385
                    in_use=10,
 
1386
                    reserved=0,
 
1387
                    ),
 
1388
                floating_ips=dict(
 
1389
                    limit=10,
 
1390
                    in_use=2,
 
1391
                    reserved=0,
 
1392
                    ),
 
1393
                metadata_items=dict(
 
1394
                    limit=128,
 
1395
                    in_use=0,
 
1396
                    reserved=0,
 
1397
                    ),
 
1398
                injected_files=dict(
 
1399
                    limit=2,
 
1400
                    in_use=0,
 
1401
                    reserved=0,
 
1402
                    ),
 
1403
                injected_file_content_bytes=dict(
 
1404
                    limit=10 * 1024,
 
1405
                    in_use=0,
 
1406
                    reserved=0,
 
1407
                    ),
 
1408
                injected_file_path_bytes=dict(
 
1409
                    limit=127,
 
1410
                    in_use=0,
 
1411
                    reserved=0,
 
1412
                    ),
 
1413
                security_groups=dict(
 
1414
                    limit=10,
 
1415
                    in_use=0,
 
1416
                    reserved=0,
 
1417
                    ),
 
1418
                security_group_rules=dict(
 
1419
                    limit=20,
 
1420
                    in_use=0,
 
1421
                    reserved=0,
 
1422
                    ),
 
1423
                key_pairs=dict(
 
1424
                    limit=100,
 
1425
                    in_use=0,
 
1426
                    reserved=0,
 
1427
                    ),
 
1428
                ))
 
1429
 
 
1430
    def test_get_project_quotas_alt_context_with_class(self):
 
1431
        self._stub_get_by_project()
 
1432
        result = self.driver.get_project_quotas(
 
1433
            FakeContext('other_project', 'other_class'),
 
1434
            quota.QUOTAS._resources, 'test_project', quota_class='test_class')
 
1435
 
 
1436
        self.assertEqual(self.calls, [
 
1437
                'quota_get_all_by_project',
 
1438
                'quota_usage_get_all_by_project',
 
1439
                'quota_class_get_all_by_name',
 
1440
                ])
 
1441
        self.assertEqual(result, dict(
 
1442
                instances=dict(
 
1443
                    limit=5,
 
1444
                    in_use=2,
 
1445
                    reserved=2,
 
1446
                    ),
 
1447
                cores=dict(
 
1448
                    limit=10,
 
1449
                    in_use=4,
 
1450
                    reserved=4,
 
1451
                    ),
 
1452
                ram=dict(
 
1453
                    limit=25 * 1024,
 
1454
                    in_use=10 * 1024,
 
1455
                    reserved=0,
 
1456
                    ),
 
1457
                volumes=dict(
 
1458
                    limit=10,
 
1459
                    in_use=2,
 
1460
                    reserved=0,
 
1461
                    ),
 
1462
                gigabytes=dict(
 
1463
                    limit=50,
 
1464
                    in_use=10,
 
1465
                    reserved=0,
 
1466
                    ),
 
1467
                floating_ips=dict(
 
1468
                    limit=10,
 
1469
                    in_use=2,
 
1470
                    reserved=0,
 
1471
                    ),
 
1472
                metadata_items=dict(
 
1473
                    limit=64,
 
1474
                    in_use=0,
 
1475
                    reserved=0,
 
1476
                    ),
 
1477
                injected_files=dict(
 
1478
                    limit=2,
 
1479
                    in_use=0,
 
1480
                    reserved=0,
 
1481
                    ),
 
1482
                injected_file_content_bytes=dict(
 
1483
                    limit=5 * 1024,
 
1484
                    in_use=0,
 
1485
                    reserved=0,
 
1486
                    ),
 
1487
                injected_file_path_bytes=dict(
 
1488
                    limit=127,
 
1489
                    in_use=0,
 
1490
                    reserved=0,
 
1491
                    ),
 
1492
                security_groups=dict(
 
1493
                    limit=10,
 
1494
                    in_use=0,
 
1495
                    reserved=0,
 
1496
                    ),
 
1497
                security_group_rules=dict(
 
1498
                    limit=20,
 
1499
                    in_use=0,
 
1500
                    reserved=0,
 
1501
                    ),
 
1502
                key_pairs=dict(
 
1503
                    limit=100,
 
1504
                    in_use=0,
 
1505
                    reserved=0,
 
1506
                    ),
 
1507
                ))
 
1508
 
 
1509
    def test_get_project_quotas_no_defaults(self):
 
1510
        self._stub_get_by_project()
 
1511
        result = self.driver.get_project_quotas(
 
1512
            FakeContext('test_project', 'test_class'),
 
1513
            quota.QUOTAS._resources, 'test_project', defaults=False)
 
1514
 
 
1515
        self.assertEqual(self.calls, [
 
1516
                'quota_get_all_by_project',
 
1517
                'quota_usage_get_all_by_project',
 
1518
                'quota_class_get_all_by_name',
 
1519
                ])
 
1520
        self.assertEqual(result, dict(
 
1521
                cores=dict(
 
1522
                    limit=10,
 
1523
                    in_use=4,
 
1524
                    reserved=4,
 
1525
                    ),
 
1526
                gigabytes=dict(
 
1527
                    limit=50,
 
1528
                    in_use=10,
 
1529
                    reserved=0,
 
1530
                    ),
 
1531
                injected_files=dict(
 
1532
                    limit=2,
 
1533
                    in_use=0,
 
1534
                    reserved=0,
 
1535
                    ),
 
1536
                injected_file_path_bytes=dict(
 
1537
                    limit=127,
 
1538
                    in_use=0,
 
1539
                    reserved=0,
 
1540
                    ),
 
1541
                ))
 
1542
 
 
1543
    def test_get_project_quotas_no_usages(self):
 
1544
        self._stub_get_by_project()
 
1545
        result = self.driver.get_project_quotas(
 
1546
            FakeContext('test_project', 'test_class'),
 
1547
            quota.QUOTAS._resources, 'test_project', usages=False)
 
1548
 
 
1549
        self.assertEqual(self.calls, [
 
1550
                'quota_get_all_by_project',
 
1551
                'quota_class_get_all_by_name',
 
1552
                ])
 
1553
        self.assertEqual(result, dict(
 
1554
                instances=dict(
 
1555
                    limit=5,
 
1556
                    ),
 
1557
                cores=dict(
 
1558
                    limit=10,
 
1559
                    ),
 
1560
                ram=dict(
 
1561
                    limit=25 * 1024,
 
1562
                    ),
 
1563
                volumes=dict(
 
1564
                    limit=10,
 
1565
                    ),
 
1566
                gigabytes=dict(
 
1567
                    limit=50,
 
1568
                    ),
 
1569
                floating_ips=dict(
 
1570
                    limit=10,
 
1571
                    ),
 
1572
                metadata_items=dict(
 
1573
                    limit=64,
 
1574
                    ),
 
1575
                injected_files=dict(
 
1576
                    limit=2,
 
1577
                    ),
 
1578
                injected_file_content_bytes=dict(
 
1579
                    limit=5 * 1024,
 
1580
                    ),
 
1581
                injected_file_path_bytes=dict(
 
1582
                    limit=127,
 
1583
                    ),
 
1584
                security_groups=dict(
 
1585
                    limit=10,
 
1586
                    ),
 
1587
                security_group_rules=dict(
 
1588
                    limit=20,
 
1589
                    ),
 
1590
                key_pairs=dict(
 
1591
                    limit=100,
 
1592
                    ),
 
1593
                ))
 
1594
 
 
1595
    def _stub_get_project_quotas(self):
 
1596
        def fake_get_project_quotas(context, resources, project_id,
 
1597
                                    quota_class=None, defaults=True,
 
1598
                                    usages=True):
 
1599
            self.calls.append('get_project_quotas')
 
1600
            return dict((k, dict(limit=v.default))
 
1601
                        for k, v in resources.items())
 
1602
 
 
1603
        self.stubs.Set(self.driver, 'get_project_quotas',
 
1604
                       fake_get_project_quotas)
 
1605
 
 
1606
    def test_get_quotas_has_sync_unknown(self):
 
1607
        self._stub_get_project_quotas()
 
1608
        self.assertRaises(exception.QuotaResourceUnknown,
 
1609
                          self.driver._get_quotas,
 
1610
                          None, quota.QUOTAS._resources,
 
1611
                          ['unknown'], True)
 
1612
        self.assertEqual(self.calls, [])
 
1613
 
 
1614
    def test_get_quotas_no_sync_unknown(self):
 
1615
        self._stub_get_project_quotas()
 
1616
        self.assertRaises(exception.QuotaResourceUnknown,
 
1617
                          self.driver._get_quotas,
 
1618
                          None, quota.QUOTAS._resources,
 
1619
                          ['unknown'], False)
 
1620
        self.assertEqual(self.calls, [])
 
1621
 
 
1622
    def test_get_quotas_has_sync_no_sync_resource(self):
 
1623
        self._stub_get_project_quotas()
 
1624
        self.assertRaises(exception.QuotaResourceUnknown,
 
1625
                          self.driver._get_quotas,
 
1626
                          None, quota.QUOTAS._resources,
 
1627
                          ['metadata_items'], True)
 
1628
        self.assertEqual(self.calls, [])
 
1629
 
 
1630
    def test_get_quotas_no_sync_has_sync_resource(self):
 
1631
        self._stub_get_project_quotas()
 
1632
        self.assertRaises(exception.QuotaResourceUnknown,
 
1633
                          self.driver._get_quotas,
 
1634
                          None, quota.QUOTAS._resources,
 
1635
                          ['instances'], False)
 
1636
        self.assertEqual(self.calls, [])
 
1637
 
 
1638
    def test_get_quotas_has_sync(self):
 
1639
        self._stub_get_project_quotas()
 
1640
        result = self.driver._get_quotas(FakeContext('test_project',
 
1641
                                                     'test_class'),
 
1642
                                         quota.QUOTAS._resources,
 
1643
                                         ['instances', 'cores', 'ram',
 
1644
                                          'volumes', 'gigabytes',
 
1645
                                          'floating_ips', 'security_groups'],
 
1646
                                         True)
 
1647
 
 
1648
        self.assertEqual(self.calls, ['get_project_quotas'])
 
1649
        self.assertEqual(result, dict(
 
1650
                instances=10,
 
1651
                cores=20,
 
1652
                ram=50 * 1024,
 
1653
                volumes=10,
 
1654
                gigabytes=1000,
 
1655
                floating_ips=10,
 
1656
                security_groups=10,
 
1657
                ))
 
1658
 
 
1659
    def test_get_quotas_no_sync(self):
 
1660
        self._stub_get_project_quotas()
 
1661
        result = self.driver._get_quotas(FakeContext('test_project',
 
1662
                                                     'test_class'),
 
1663
                                         quota.QUOTAS._resources,
 
1664
                                         ['metadata_items', 'injected_files',
 
1665
                                          'injected_file_content_bytes',
 
1666
                                          'injected_file_path_bytes',
 
1667
                                          'security_group_rules'], False)
 
1668
 
 
1669
        self.assertEqual(self.calls, ['get_project_quotas'])
 
1670
        self.assertEqual(result, dict(
 
1671
                metadata_items=128,
 
1672
                injected_files=5,
 
1673
                injected_file_content_bytes=10 * 1024,
 
1674
                injected_file_path_bytes=255,
 
1675
                security_group_rules=20,
 
1676
                ))
 
1677
 
 
1678
    def test_limit_check_under(self):
 
1679
        self._stub_get_project_quotas()
 
1680
        self.assertRaises(exception.InvalidQuotaValue,
 
1681
                          self.driver.limit_check,
 
1682
                          FakeContext('test_project', 'test_class'),
 
1683
                          quota.QUOTAS._resources,
 
1684
                          dict(metadata_items=-1))
 
1685
 
 
1686
    def test_limit_check_over(self):
 
1687
        self._stub_get_project_quotas()
 
1688
        self.assertRaises(exception.OverQuota,
 
1689
                          self.driver.limit_check,
 
1690
                          FakeContext('test_project', 'test_class'),
 
1691
                          quota.QUOTAS._resources,
 
1692
                          dict(metadata_items=129))
 
1693
 
 
1694
    def test_limit_check_unlimited(self):
 
1695
        self.flags(quota_metadata_items=-1)
 
1696
        self._stub_get_project_quotas()
 
1697
        self.driver.limit_check(FakeContext('test_project', 'test_class'),
 
1698
                                quota.QUOTAS._resources,
 
1699
                                dict(metadata_items=32767))
 
1700
 
 
1701
    def test_limit_check(self):
 
1702
        self._stub_get_project_quotas()
 
1703
        self.driver.limit_check(FakeContext('test_project', 'test_class'),
 
1704
                                quota.QUOTAS._resources,
 
1705
                                dict(metadata_items=128))
 
1706
 
 
1707
    def _stub_quota_reserve(self):
 
1708
        def fake_quota_reserve(context, resources, quotas, deltas, expire,
 
1709
                               until_refresh, max_age):
 
1710
            self.calls.append(('quota_reserve', expire, until_refresh,
 
1711
                               max_age))
 
1712
            return ['resv-1', 'resv-2', 'resv-3']
 
1713
        self.stubs.Set(db, 'quota_reserve', fake_quota_reserve)
 
1714
 
 
1715
    def test_reserve_bad_expire(self):
 
1716
        self._stub_get_project_quotas()
 
1717
        self._stub_quota_reserve()
 
1718
        self.assertRaises(exception.InvalidReservationExpiration,
 
1719
                          self.driver.reserve,
 
1720
                          FakeContext('test_project', 'test_class'),
 
1721
                          quota.QUOTAS._resources,
 
1722
                          dict(instances=2), expire='invalid')
 
1723
        self.assertEqual(self.calls, [])
 
1724
 
 
1725
    def test_reserve_default_expire(self):
 
1726
        self._stub_get_project_quotas()
 
1727
        self._stub_quota_reserve()
 
1728
        result = self.driver.reserve(FakeContext('test_project', 'test_class'),
 
1729
                                     quota.QUOTAS._resources,
 
1730
                                     dict(instances=2))
 
1731
 
 
1732
        expire = utils.utcnow() + datetime.timedelta(seconds=86400)
 
1733
        self.assertEqual(self.calls, [
 
1734
                'get_project_quotas',
 
1735
                ('quota_reserve', expire, 0, 0),
 
1736
                ])
 
1737
        self.assertEqual(result, ['resv-1', 'resv-2', 'resv-3'])
 
1738
 
 
1739
    def test_reserve_int_expire(self):
 
1740
        self._stub_get_project_quotas()
 
1741
        self._stub_quota_reserve()
 
1742
        result = self.driver.reserve(FakeContext('test_project', 'test_class'),
 
1743
                                     quota.QUOTAS._resources,
 
1744
                                     dict(instances=2), expire=3600)
 
1745
 
 
1746
        expire = utils.utcnow() + datetime.timedelta(seconds=3600)
 
1747
        self.assertEqual(self.calls, [
 
1748
                'get_project_quotas',
 
1749
                ('quota_reserve', expire, 0, 0),
 
1750
                ])
 
1751
        self.assertEqual(result, ['resv-1', 'resv-2', 'resv-3'])
 
1752
 
 
1753
    def test_reserve_timedelta_expire(self):
 
1754
        self._stub_get_project_quotas()
 
1755
        self._stub_quota_reserve()
 
1756
        expire_delta = datetime.timedelta(seconds=60)
 
1757
        result = self.driver.reserve(FakeContext('test_project', 'test_class'),
 
1758
                                     quota.QUOTAS._resources,
 
1759
                                     dict(instances=2), expire=expire_delta)
 
1760
 
 
1761
        expire = utils.utcnow() + expire_delta
 
1762
        self.assertEqual(self.calls, [
 
1763
                'get_project_quotas',
 
1764
                ('quota_reserve', expire, 0, 0),
 
1765
                ])
 
1766
        self.assertEqual(result, ['resv-1', 'resv-2', 'resv-3'])
 
1767
 
 
1768
    def test_reserve_datetime_expire(self):
 
1769
        self._stub_get_project_quotas()
 
1770
        self._stub_quota_reserve()
 
1771
        expire = utils.utcnow() + datetime.timedelta(seconds=120)
 
1772
        result = self.driver.reserve(FakeContext('test_project', 'test_class'),
 
1773
                                     quota.QUOTAS._resources,
 
1774
                                     dict(instances=2), expire=expire)
 
1775
 
 
1776
        self.assertEqual(self.calls, [
 
1777
                'get_project_quotas',
 
1778
                ('quota_reserve', expire, 0, 0),
 
1779
                ])
 
1780
        self.assertEqual(result, ['resv-1', 'resv-2', 'resv-3'])
 
1781
 
 
1782
    def test_reserve_until_refresh(self):
 
1783
        self._stub_get_project_quotas()
 
1784
        self._stub_quota_reserve()
 
1785
        self.flags(until_refresh=500)
 
1786
        expire = utils.utcnow() + datetime.timedelta(seconds=120)
 
1787
        result = self.driver.reserve(FakeContext('test_project', 'test_class'),
 
1788
                                     quota.QUOTAS._resources,
 
1789
                                     dict(instances=2), expire=expire)
 
1790
 
 
1791
        self.assertEqual(self.calls, [
 
1792
                'get_project_quotas',
 
1793
                ('quota_reserve', expire, 500, 0),
 
1794
                ])
 
1795
        self.assertEqual(result, ['resv-1', 'resv-2', 'resv-3'])
 
1796
 
 
1797
    def test_reserve_max_age(self):
 
1798
        self._stub_get_project_quotas()
 
1799
        self._stub_quota_reserve()
 
1800
        self.flags(max_age=86400)
 
1801
        expire = utils.utcnow() + datetime.timedelta(seconds=120)
 
1802
        result = self.driver.reserve(FakeContext('test_project', 'test_class'),
 
1803
                                     quota.QUOTAS._resources,
 
1804
                                     dict(instances=2), expire=expire)
 
1805
 
 
1806
        self.assertEqual(self.calls, [
 
1807
                'get_project_quotas',
 
1808
                ('quota_reserve', expire, 0, 86400),
 
1809
                ])
 
1810
        self.assertEqual(result, ['resv-1', 'resv-2', 'resv-3'])
 
1811
 
 
1812
 
 
1813
class FakeSession(object):
 
1814
    def begin(self):
 
1815
        return self
 
1816
 
 
1817
    def __enter__(self):
 
1818
        return self
 
1819
 
 
1820
    def __exit__(self, exc_type, exc_value, exc_traceback):
 
1821
        return False
 
1822
 
 
1823
 
 
1824
class FakeUsage(sqa_models.QuotaUsage):
 
1825
    def save(self, *args, **kwargs):
 
1826
        pass
 
1827
 
 
1828
 
 
1829
class QuotaReserveSqlAlchemyTestCase(test.TestCase):
 
1830
    # nova.db.sqlalchemy.api.quota_reserve is so complex it needs its
 
1831
    # own test case, and since it's a quota manipulator, this is the
 
1832
    # best place to put it...
 
1833
 
 
1834
    def setUp(self):
 
1835
        super(QuotaReserveSqlAlchemyTestCase, self).setUp()
 
1836
 
 
1837
        self.sync_called = set()
 
1838
 
 
1839
        def make_sync(res_name):
 
1840
            def sync(context, project_id, session):
 
1841
                self.sync_called.add(res_name)
 
1842
                if res_name in self.usages:
 
1843
                    return {res_name: self.usages[res_name].in_use - 1}
 
1844
                return {res_name: 0}
 
1845
            return sync
 
1846
 
 
1847
        self.resources = {}
 
1848
        for res_name in ('instances', 'cores', 'ram'):
 
1849
            res = quota.ReservableResource(res_name, make_sync(res_name))
 
1850
            self.resources[res_name] = res
 
1851
 
 
1852
        self.expire = utils.utcnow() + datetime.timedelta(seconds=3600)
 
1853
 
 
1854
        self.usages = {}
 
1855
        self.usages_created = {}
 
1856
        self.reservations_created = {}
 
1857
 
 
1858
        def fake_get_session():
 
1859
            return FakeSession()
 
1860
 
 
1861
        def fake_get_quota_usages(context, session, keys):
 
1862
            return self.usages.copy()
 
1863
 
 
1864
        def fake_quota_usage_create(context, project_id, resource, in_use,
 
1865
                                    reserved, until_refresh, session=None,
 
1866
                                    save=True):
 
1867
            quota_usage_ref = self._make_quota_usage(
 
1868
                project_id, resource, in_use, reserved, until_refresh,
 
1869
                utils.utcnow(), utils.utcnow())
 
1870
 
 
1871
            self.usages_created[resource] = quota_usage_ref
 
1872
 
 
1873
            return quota_usage_ref
 
1874
 
 
1875
        def fake_reservation_create(context, uuid, usage_id, project_id,
 
1876
                                    resource, delta, expire, session=None):
 
1877
            reservation_ref = self._make_reservation(
 
1878
                uuid, usage_id, project_id, resource, delta, expire,
 
1879
                utils.utcnow(), utils.utcnow())
 
1880
 
 
1881
            self.reservations_created[resource] = reservation_ref
 
1882
 
 
1883
            return reservation_ref
 
1884
 
 
1885
        self.stubs.Set(sqa_api, 'get_session', fake_get_session)
 
1886
        self.stubs.Set(sqa_api, '_get_quota_usages', fake_get_quota_usages)
 
1887
        self.stubs.Set(sqa_api, 'quota_usage_create', fake_quota_usage_create)
 
1888
        self.stubs.Set(sqa_api, 'reservation_create', fake_reservation_create)
 
1889
 
 
1890
        utils.set_time_override()
 
1891
 
 
1892
    def _make_quota_usage(self, project_id, resource, in_use, reserved,
 
1893
                          until_refresh, created_at, updated_at):
 
1894
        quota_usage_ref = FakeUsage()
 
1895
        quota_usage_ref.id = len(self.usages) + len(self.usages_created)
 
1896
        quota_usage_ref.project_id = project_id
 
1897
        quota_usage_ref.resource = resource
 
1898
        quota_usage_ref.in_use = in_use
 
1899
        quota_usage_ref.reserved = reserved
 
1900
        quota_usage_ref.until_refresh = until_refresh
 
1901
        quota_usage_ref.created_at = created_at
 
1902
        quota_usage_ref.updated_at = updated_at
 
1903
        quota_usage_ref.deleted_at = None
 
1904
        quota_usage_ref.deleted = False
 
1905
 
 
1906
        return quota_usage_ref
 
1907
 
 
1908
    def init_usage(self, project_id, resource, in_use, reserved,
 
1909
                   until_refresh=None, created_at=None, updated_at=None):
 
1910
        if created_at is None:
 
1911
            created_at = utils.utcnow()
 
1912
        if updated_at is None:
 
1913
            updated_at = utils.utcnow()
 
1914
 
 
1915
        quota_usage_ref = self._make_quota_usage(project_id, resource, in_use,
 
1916
                                                 reserved, until_refresh,
 
1917
                                                 created_at, updated_at)
 
1918
 
 
1919
        self.usages[resource] = quota_usage_ref
 
1920
 
 
1921
    def compare_usage(self, usage_dict, expected):
 
1922
        for usage in expected:
 
1923
            resource = usage['resource']
 
1924
            for key, value in usage.items():
 
1925
                actual = getattr(usage_dict[resource], key)
 
1926
                self.assertEqual(actual, value,
 
1927
                                 "%s != %s on usage for resource %s" %
 
1928
                                 (actual, value, resource))
 
1929
 
 
1930
    def _make_reservation(self, uuid, usage_id, project_id, resource,
 
1931
                          delta, expire, created_at, updated_at):
 
1932
        reservation_ref = sqa_models.Reservation()
 
1933
        reservation_ref.id = len(self.reservations_created)
 
1934
        reservation_ref.uuid = uuid
 
1935
        reservation_ref.usage_id = usage_id
 
1936
        reservation_ref.project_id = project_id
 
1937
        reservation_ref.resource = resource
 
1938
        reservation_ref.delta = delta
 
1939
        reservation_ref.expire = expire
 
1940
        reservation_ref.created_at = created_at
 
1941
        reservation_ref.updated_at = updated_at
 
1942
        reservation_ref.deleted_at = None
 
1943
        reservation_ref.deleted = False
 
1944
 
 
1945
        return reservation_ref
 
1946
 
 
1947
    def compare_reservation(self, reservations, expected):
 
1948
        reservations = set(reservations)
 
1949
        for resv in expected:
 
1950
            resource = resv['resource']
 
1951
            resv_obj = self.reservations_created[resource]
 
1952
 
 
1953
            self.assertIn(resv_obj.uuid, reservations)
 
1954
            reservations.discard(resv_obj.uuid)
 
1955
 
 
1956
            for key, value in resv.items():
 
1957
                actual = getattr(resv_obj, key)
 
1958
                self.assertEqual(actual, value,
 
1959
                                 "%s != %s on reservation for resource %s" %
 
1960
                                 (actual, value, resource))
 
1961
 
 
1962
        self.assertEqual(len(reservations), 0)
 
1963
 
 
1964
    def test_quota_reserve_create_usages(self):
 
1965
        context = FakeContext('test_project', 'test_class')
 
1966
        quotas = dict(
 
1967
            instances=5,
 
1968
            cores=10,
 
1969
            ram=10 * 1024,
 
1970
            )
 
1971
        deltas = dict(
 
1972
            instances=2,
 
1973
            cores=4,
 
1974
            ram=2 * 1024,
 
1975
            )
 
1976
        result = sqa_api.quota_reserve(context, self.resources, quotas,
 
1977
                                       deltas, self.expire, 0, 0)
 
1978
 
 
1979
        self.assertEqual(self.sync_called, set(['instances', 'cores', 'ram']))
 
1980
        self.compare_usage(self.usages_created, [
 
1981
                dict(resource='instances',
 
1982
                     project_id='test_project',
 
1983
                     in_use=0,
 
1984
                     reserved=2,
 
1985
                     until_refresh=None),
 
1986
                dict(resource='cores',
 
1987
                     project_id='test_project',
 
1988
                     in_use=0,
 
1989
                     reserved=4,
 
1990
                     until_refresh=None),
 
1991
                dict(resource='ram',
 
1992
                     project_id='test_project',
 
1993
                     in_use=0,
 
1994
                     reserved=2 * 1024,
 
1995
                     until_refresh=None),
 
1996
                ])
 
1997
        self.compare_reservation(result, [
 
1998
                dict(resource='instances',
 
1999
                     usage_id=self.usages_created['instances'],
 
2000
                     project_id='test_project',
 
2001
                     delta=2),
 
2002
                dict(resource='cores',
 
2003
                     usage_id=self.usages_created['cores'],
 
2004
                     project_id='test_project',
 
2005
                     delta=4),
 
2006
                dict(resource='ram',
 
2007
                     usage_id=self.usages_created['ram'],
 
2008
                     delta=2 * 1024),
 
2009
                ])
 
2010
 
 
2011
    def test_quota_reserve_until_refresh(self):
 
2012
        self.init_usage('test_project', 'instances', 3, 0, until_refresh=1)
 
2013
        self.init_usage('test_project', 'cores', 3, 0, until_refresh=1)
 
2014
        self.init_usage('test_project', 'ram', 3, 0, until_refresh=1)
 
2015
        context = FakeContext('test_project', 'test_class')
 
2016
        quotas = dict(
 
2017
            instances=5,
 
2018
            cores=10,
 
2019
            ram=10 * 1024,
 
2020
            )
 
2021
        deltas = dict(
 
2022
            instances=2,
 
2023
            cores=4,
 
2024
            ram=2 * 1024,
 
2025
            )
 
2026
        result = sqa_api.quota_reserve(context, self.resources, quotas,
 
2027
                                       deltas, self.expire, 5, 0)
 
2028
 
 
2029
        self.assertEqual(self.sync_called, set(['instances', 'cores', 'ram']))
 
2030
        self.compare_usage(self.usages, [
 
2031
                dict(resource='instances',
 
2032
                     project_id='test_project',
 
2033
                     in_use=2,
 
2034
                     reserved=2,
 
2035
                     until_refresh=5),
 
2036
                dict(resource='cores',
 
2037
                     project_id='test_project',
 
2038
                     in_use=2,
 
2039
                     reserved=4,
 
2040
                     until_refresh=5),
 
2041
                dict(resource='ram',
 
2042
                     project_id='test_project',
 
2043
                     in_use=2,
 
2044
                     reserved=2 * 1024,
 
2045
                     until_refresh=5),
 
2046
                ])
 
2047
        self.assertEqual(self.usages_created, {})
 
2048
        self.compare_reservation(result, [
 
2049
                dict(resource='instances',
 
2050
                     usage_id=self.usages['instances'],
 
2051
                     project_id='test_project',
 
2052
                     delta=2),
 
2053
                dict(resource='cores',
 
2054
                     usage_id=self.usages['cores'],
 
2055
                     project_id='test_project',
 
2056
                     delta=4),
 
2057
                dict(resource='ram',
 
2058
                     usage_id=self.usages['ram'],
 
2059
                     delta=2 * 1024),
 
2060
                ])
 
2061
 
 
2062
    def test_quota_reserve_max_age(self):
 
2063
        max_age = 3600
 
2064
        record_created = utils.utcnow() - datetime.timedelta(seconds=max_age)
 
2065
        self.init_usage('test_project', 'instances', 3, 0,
 
2066
                        created_at=record_created, updated_at=record_created)
 
2067
        self.init_usage('test_project', 'cores', 3, 0,
 
2068
                        created_at=record_created, updated_at=record_created)
 
2069
        self.init_usage('test_project', 'ram', 3, 0,
 
2070
                        created_at=record_created, updated_at=record_created)
 
2071
        context = FakeContext('test_project', 'test_class')
 
2072
        quotas = dict(
 
2073
            instances=5,
 
2074
            cores=10,
 
2075
            ram=10 * 1024,
 
2076
            )
 
2077
        deltas = dict(
 
2078
            instances=2,
 
2079
            cores=4,
 
2080
            ram=2 * 1024,
 
2081
            )
 
2082
        result = sqa_api.quota_reserve(context, self.resources, quotas,
 
2083
                                       deltas, self.expire, 0, max_age)
 
2084
 
 
2085
        self.assertEqual(self.sync_called, set(['instances', 'cores', 'ram']))
 
2086
        self.compare_usage(self.usages, [
 
2087
                dict(resource='instances',
 
2088
                     project_id='test_project',
 
2089
                     in_use=2,
 
2090
                     reserved=2,
 
2091
                     until_refresh=None),
 
2092
                dict(resource='cores',
 
2093
                     project_id='test_project',
 
2094
                     in_use=2,
 
2095
                     reserved=4,
 
2096
                     until_refresh=None),
 
2097
                dict(resource='ram',
 
2098
                     project_id='test_project',
 
2099
                     in_use=2,
 
2100
                     reserved=2 * 1024,
 
2101
                     until_refresh=None),
 
2102
                ])
 
2103
        self.assertEqual(self.usages_created, {})
 
2104
        self.compare_reservation(result, [
 
2105
                dict(resource='instances',
 
2106
                     usage_id=self.usages['instances'],
 
2107
                     project_id='test_project',
 
2108
                     delta=2),
 
2109
                dict(resource='cores',
 
2110
                     usage_id=self.usages['cores'],
 
2111
                     project_id='test_project',
 
2112
                     delta=4),
 
2113
                dict(resource='ram',
 
2114
                     usage_id=self.usages['ram'],
 
2115
                     delta=2 * 1024),
 
2116
                ])
 
2117
 
 
2118
    def test_quota_reserve_no_refresh(self):
 
2119
        self.init_usage('test_project', 'instances', 3, 0)
 
2120
        self.init_usage('test_project', 'cores', 3, 0)
 
2121
        self.init_usage('test_project', 'ram', 3, 0)
 
2122
        context = FakeContext('test_project', 'test_class')
 
2123
        quotas = dict(
 
2124
            instances=5,
 
2125
            cores=10,
 
2126
            ram=10 * 1024,
 
2127
            )
 
2128
        deltas = dict(
 
2129
            instances=2,
 
2130
            cores=4,
 
2131
            ram=2 * 1024,
 
2132
            )
 
2133
        result = sqa_api.quota_reserve(context, self.resources, quotas,
 
2134
                                       deltas, self.expire, 0, 0)
 
2135
 
 
2136
        self.assertEqual(self.sync_called, set([]))
 
2137
        self.compare_usage(self.usages, [
 
2138
                dict(resource='instances',
 
2139
                     project_id='test_project',
 
2140
                     in_use=3,
 
2141
                     reserved=2,
 
2142
                     until_refresh=None),
 
2143
                dict(resource='cores',
 
2144
                     project_id='test_project',
 
2145
                     in_use=3,
 
2146
                     reserved=4,
 
2147
                     until_refresh=None),
 
2148
                dict(resource='ram',
 
2149
                     project_id='test_project',
 
2150
                     in_use=3,
 
2151
                     reserved=2 * 1024,
 
2152
                     until_refresh=None),
 
2153
                ])
 
2154
        self.assertEqual(self.usages_created, {})
 
2155
        self.compare_reservation(result, [
 
2156
                dict(resource='instances',
 
2157
                     usage_id=self.usages['instances'],
 
2158
                     project_id='test_project',
 
2159
                     delta=2),
 
2160
                dict(resource='cores',
 
2161
                     usage_id=self.usages['cores'],
 
2162
                     project_id='test_project',
 
2163
                     delta=4),
 
2164
                dict(resource='ram',
 
2165
                     usage_id=self.usages['ram'],
 
2166
                     delta=2 * 1024),
 
2167
                ])
 
2168
 
 
2169
    def test_quota_reserve_unders(self):
 
2170
        self.init_usage('test_project', 'instances', 1, 0)
 
2171
        self.init_usage('test_project', 'cores', 3, 0)
 
2172
        self.init_usage('test_project', 'ram', 1 * 1024, 0)
 
2173
        context = FakeContext('test_project', 'test_class')
 
2174
        quotas = dict(
 
2175
            instances=5,
 
2176
            cores=10,
 
2177
            ram=10 * 1024,
 
2178
            )
 
2179
        deltas = dict(
 
2180
            instances=-2,
 
2181
            cores=-4,
 
2182
            ram=-2 * 1024,
 
2183
            )
 
2184
        self.assertRaises(exception.InvalidQuotaValue,
 
2185
                          sqa_api.quota_reserve,
 
2186
                          context, self.resources, quotas,
 
2187
                          deltas, self.expire, 0, 0)
 
2188
 
 
2189
        self.assertEqual(self.sync_called, set([]))
 
2190
        self.compare_usage(self.usages, [
 
2191
                dict(resource='instances',
 
2192
                     project_id='test_project',
 
2193
                     in_use=1,
 
2194
                     reserved=0,
 
2195
                     until_refresh=None),
 
2196
                dict(resource='cores',
 
2197
                     project_id='test_project',
 
2198
                     in_use=3,
 
2199
                     reserved=0,
 
2200
                     until_refresh=None),
 
2201
                dict(resource='ram',
 
2202
                     project_id='test_project',
 
2203
                     in_use=1 * 1024,
 
2204
                     reserved=0,
 
2205
                     until_refresh=None),
 
2206
                ])
 
2207
        self.assertEqual(self.usages_created, {})
 
2208
        self.assertEqual(self.reservations_created, {})
 
2209
 
 
2210
    def test_quota_reserve_overs(self):
 
2211
        self.init_usage('test_project', 'instances', 4, 0)
 
2212
        self.init_usage('test_project', 'cores', 8, 0)
 
2213
        self.init_usage('test_project', 'ram', 10 * 1024, 0)
 
2214
        context = FakeContext('test_project', 'test_class')
 
2215
        quotas = dict(
 
2216
            instances=5,
 
2217
            cores=10,
 
2218
            ram=10 * 1024,
 
2219
            )
 
2220
        deltas = dict(
 
2221
            instances=2,
 
2222
            cores=4,
 
2223
            ram=2 * 1024,
 
2224
            )
 
2225
        self.assertRaises(exception.OverQuota,
 
2226
                          sqa_api.quota_reserve,
 
2227
                          context, self.resources, quotas,
 
2228
                          deltas, self.expire, 0, 0)
 
2229
 
 
2230
        self.assertEqual(self.sync_called, set([]))
 
2231
        self.compare_usage(self.usages, [
 
2232
                dict(resource='instances',
 
2233
                     project_id='test_project',
 
2234
                     in_use=4,
 
2235
                     reserved=0,
 
2236
                     until_refresh=None),
 
2237
                dict(resource='cores',
 
2238
                     project_id='test_project',
 
2239
                     in_use=8,
 
2240
                     reserved=0,
 
2241
                     until_refresh=None),
 
2242
                dict(resource='ram',
 
2243
                     project_id='test_project',
 
2244
                     in_use=10 * 1024,
 
2245
                     reserved=0,
 
2246
                     until_refresh=None),
 
2247
                ])
 
2248
        self.assertEqual(self.usages_created, {})
 
2249
        self.assertEqual(self.reservations_created, {})
 
2250
 
 
2251
    def test_quota_reserve_reduction(self):
 
2252
        self.init_usage('test_project', 'instances', 10, 0)
 
2253
        self.init_usage('test_project', 'cores', 20, 0)
 
2254
        self.init_usage('test_project', 'ram', 20 * 1024, 0)
 
2255
        context = FakeContext('test_project', 'test_class')
 
2256
        quotas = dict(
 
2257
            instances=5,
 
2258
            cores=10,
 
2259
            ram=10 * 1024,
 
2260
            )
 
2261
        deltas = dict(
 
2262
            instances=-2,
 
2263
            cores=-4,
 
2264
            ram=-2 * 1024,
 
2265
            )
 
2266
        result = sqa_api.quota_reserve(context, self.resources, quotas,
 
2267
                                       deltas, self.expire, 0, 0)
 
2268
 
 
2269
        self.assertEqual(self.sync_called, set([]))
 
2270
        self.compare_usage(self.usages, [
 
2271
                dict(resource='instances',
 
2272
                     project_id='test_project',
 
2273
                     in_use=10,
 
2274
                     reserved=0,
 
2275
                     until_refresh=None),
 
2276
                dict(resource='cores',
 
2277
                     project_id='test_project',
 
2278
                     in_use=20,
 
2279
                     reserved=0,
 
2280
                     until_refresh=None),
 
2281
                dict(resource='ram',
 
2282
                     project_id='test_project',
 
2283
                     in_use=20 * 1024,
 
2284
                     reserved=0,
 
2285
                     until_refresh=None),
 
2286
                ])
 
2287
        self.assertEqual(self.usages_created, {})
 
2288
        self.compare_reservation(result, [
 
2289
                dict(resource='instances',
 
2290
                     usage_id=self.usages['instances'],
 
2291
                     project_id='test_project',
 
2292
                     delta=-2),
 
2293
                dict(resource='cores',
 
2294
                     usage_id=self.usages['cores'],
 
2295
                     project_id='test_project',
 
2296
                     delta=-4),
 
2297
                dict(resource='ram',
 
2298
                     usage_id=self.usages['ram'],
 
2299
                     project_id='test_project',
 
2300
                     delta=-2 * 1024),
 
2301
                ])