]> review.fuel-infra Code Review - openstack-build/cinder-build.git/commitdiff
Include allocated quota value in the quota reserve
authorRaildo Mascena <raildo@lsd.ufcg.edu.br>
Wed, 28 Oct 2015 20:50:44 +0000 (17:50 -0300)
committerRaildo Mascena <raildom@gmail.com>
Tue, 9 Feb 2016 17:08:10 +0000 (17:08 +0000)
When we do a quota_reserve in a project, the allocated quota for their
subprojects was not considered in the over quota calculation

Co-Authored-By: Paulo Ewerton <pauloewerton@lsd.ufcg.edu.br>
Change-Id: Ia72e13a40e00c4ec0e986b80a7c9a322f3df659d
Closes-Bug: #1505801

cinder/db/sqlalchemy/api.py
cinder/tests/unit/test_quota.py

index e82edd8900066ae84e5e6d7234e2fd4c11d9e389..b603a21786afe1b4ec833329522e03d91d237939 100644 (file)
@@ -774,6 +774,8 @@ def quota_reserve(context, resources, quotas, deltas, expire,
 
         # Get the current usages
         usages = _get_quota_usages(context, session, project_id)
+        allocated = quota_allocated_get_all_by_project(context, project_id)
+        allocated.pop('project_id')
 
         # Handle usage refresh
         work = set(deltas.keys())
@@ -854,7 +856,7 @@ def quota_reserve(context, resources, quotas, deltas, expire,
         #            problems.
         overs = [r for r, delta in deltas.items()
                  if quotas[r] >= 0 and delta >= 0 and
-                 quotas[r] < delta + usages[r].total]
+                 quotas[r] < delta + usages[r].total + allocated.get(r, 0)]
 
         # NOTE(Vek): The quota check needs to be in the transaction,
         #            but the transaction doesn't fail just because
index 11f792d44da4846524d1275c7abb12daf0eac481..911556ff5e10fdce3bf1b6fe99783b988a58f26e 100644 (file)
@@ -1584,12 +1584,56 @@ class QuotaReserveSqlAlchemyTestCase(test.TestCase):
 
         self.assertEqual(0, len(reservations))
 
+    def _stub_allocated_get_all_by_project(self, allocated_quota=False):
+        def fake_qagabp(context, project_id):
+            self.assertEqual('test_project', project_id)
+            if allocated_quota:
+                return dict(project_id=project_id, volumes=3,
+                            gigabytes = 2 * 1024)
+            return dict(project_id=project_id)
+
+        self.stubs.Set(sqa_api,
+                       'quota_allocated_get_all_by_project',
+                       fake_qagabp)
+
+    def test_quota_reserve_with_allocated(self):
+        context = FakeContext('test_project', 'test_class')
+        # Allocated quota for volume will be updated for 3
+        self._stub_allocated_get_all_by_project(allocated_quota=True)
+        # Quota limited for volume updated for 10
+        quotas = dict(volumes=10,
+                      gigabytes=10 * 1024, )
+        # Try reserve 7 volumes
+        deltas = dict(volumes=7,
+                      gigabytes=2 * 1024, )
+        result = sqa_api.quota_reserve(context, self.resources, quotas,
+                                       deltas, self.expire, 5, 0)
+        # The reservation works
+        self.compare_reservation(
+            result,
+            [dict(resource='volumes',
+                  usage_id=self.usages_created['volumes'],
+                  project_id='test_project',
+                  delta=7),
+             dict(resource='gigabytes',
+                  usage_id=self.usages_created['gigabytes'],
+                  delta=2 * 1024), ])
+        # But if we try reserve 8 volumes(more free quota that we have)
+        deltas = dict(volumes=8,
+                      gigabytes=2 * 1024, )
+
+        self.assertRaises(exception.OverQuota,
+                          sqa_api.quota_reserve,
+                          context, self.resources, quotas,
+                          deltas, self.expire, 0, 0)
+
     def test_quota_reserve_create_usages(self):
         context = FakeContext('test_project', 'test_class')
         quotas = dict(volumes=5,
                       gigabytes=10 * 1024, )
         deltas = dict(volumes=2,
                       gigabytes=2 * 1024, )
+        self._stub_allocated_get_all_by_project()
         result = sqa_api.quota_reserve(context, self.resources, quotas,
                                        deltas, self.expire, 0, 0)
 
@@ -1623,6 +1667,7 @@ class QuotaReserveSqlAlchemyTestCase(test.TestCase):
                       gigabytes=10 * 1024, )
         deltas = dict(volumes=2,
                       gigabytes=2 * 1024, )
+        self._stub_allocated_get_all_by_project()
         result = sqa_api.quota_reserve(context, self.resources, quotas,
                                        deltas, self.expire, 5, 0)
 
@@ -1653,6 +1698,7 @@ class QuotaReserveSqlAlchemyTestCase(test.TestCase):
         context = FakeContext('test_project', 'test_class')
         quotas = dict(volumes=5, gigabytes=10 * 1024, )
         deltas = dict(volumes=2, gigabytes=2 * 1024, )
+        self._stub_allocated_get_all_by_project()
         result = sqa_api.quota_reserve(context, self.resources, quotas,
                                        deltas, self.expire, 5, 0)
 
@@ -1688,6 +1734,7 @@ class QuotaReserveSqlAlchemyTestCase(test.TestCase):
         context = FakeContext('test_project', 'test_class')
         quotas = dict(volumes=5, gigabytes=10 * 1024, )
         deltas = dict(volumes=2, gigabytes=2 * 1024, )
+        self._stub_allocated_get_all_by_project()
         result = sqa_api.quota_reserve(context, self.resources, quotas,
                                        deltas, self.expire, 0, max_age)
 
@@ -1718,6 +1765,7 @@ class QuotaReserveSqlAlchemyTestCase(test.TestCase):
         context = FakeContext('test_project', 'test_class')
         quotas = dict(volumes=5, gigabytes=10 * 1024, )
         deltas = dict(volumes=2, gigabytes=2 * 1024, )
+        self._stub_allocated_get_all_by_project()
         result = sqa_api.quota_reserve(context, self.resources, quotas,
                                        deltas, self.expire, 0, 0)
 
@@ -1748,6 +1796,7 @@ class QuotaReserveSqlAlchemyTestCase(test.TestCase):
         context = FakeContext('test_project', 'test_class')
         quotas = dict(volumes=5, gigabytes=10 * 1024, )
         deltas = dict(volumes=-2, gigabytes=-2 * 1024, )
+        self._stub_allocated_get_all_by_project()
         result = sqa_api.quota_reserve(context, self.resources, quotas,
                                        deltas, self.expire, 0, 0)
 
@@ -1778,6 +1827,7 @@ class QuotaReserveSqlAlchemyTestCase(test.TestCase):
         context = FakeContext('test_project', 'test_class')
         quotas = dict(volumes=5, gigabytes=10 * 1024, )
         deltas = dict(volumes=2, gigabytes=2 * 1024, )
+        self._stub_allocated_get_all_by_project()
         self.assertRaises(exception.OverQuota,
                           sqa_api.quota_reserve,
                           context, self.resources, quotas,
@@ -1803,6 +1853,7 @@ class QuotaReserveSqlAlchemyTestCase(test.TestCase):
         context = FakeContext('test_project', 'test_class')
         quotas = dict(volumes=5, gigabytes=10 * 1024, )
         deltas = dict(volumes=-2, gigabytes=-2 * 1024, )
+        self._stub_allocated_get_all_by_project()
         result = sqa_api.quota_reserve(context, self.resources, quotas,
                                        deltas, self.expire, 0, 0)