diff --git a/cinder/db/sqlalchemy/api.py b/cinder/db/sqlalchemy/api.py index 082c8274c1b..bcf727383b7 100644 --- a/cinder/db/sqlalchemy/api.py +++ b/cinder/db/sqlalchemy/api.py @@ -1232,6 +1232,15 @@ def quota_reserve(context, resources, quotas, deltas, expire, # for. We don't check, because this is # a best-effort mechanism. + # There are 3 cases where we want to update "until_refresh" in the + # DB: when we enabled it, when we disabled it, and when we changed + # to a value lower than the current remaining value. + else: + res_until = usages[resource].until_refresh + if ((res_until is None and until_refresh) or + ((res_until or 0) > (until_refresh or 0))): + usages[resource].until_refresh = until_refresh or None + # Check for deltas that would go negative if is_allocated_reserve: unders = [r for r, delta in deltas.items() diff --git a/cinder/tests/unit/test_quota.py b/cinder/tests/unit/test_quota.py index e8acb62a6ba..15e8fa094b1 100644 --- a/cinder/tests/unit/test_quota.py +++ b/cinder/tests/unit/test_quota.py @@ -1695,6 +1695,57 @@ class QuotaReserveSqlAlchemyTestCase(test.TestCase): usage_id=self.usages['gigabytes'], delta=2 * 1024), ]) + def test_quota_reserve_until_refresh_enable(self): + """Test that enabling until_refresh works.""" + # Simulate service running with until_refresh disabled + self.init_usage('test_project', 'volumes', 3, 0, until_refresh=None) + self.init_usage('test_project', 'gigabytes', 100, 0, + until_refresh=None) + context = FakeContext('test_project', 'test_class') + quotas = dict(volumes=5, gigabytes=10 * 1024, ) + deltas = dict(volumes=2, gigabytes=2 * 1024, ) + self._mock_allocated_get_all_by_project() + + # Simulate service is now running with until_refresh set to 5 + sqa_api.quota_reserve(context, self.resources, quotas, deltas, + self.expire, 5, 0) + + self.compare_usage(self.usages, [dict(resource='volumes', + project_id='test_project', + in_use=3, + reserved=2, + until_refresh=5), + dict(resource='gigabytes', + project_id='test_project', + in_use=100, + reserved=2 * 1024, + until_refresh=5), ]) + + def test_quota_reserve_until_refresh_disable(self): + """Test that disabling until_refresh works.""" + # Simulate service running with until_refresh enabled and set to 5 + self.init_usage('test_project', 'volumes', 3, 0, until_refresh=5) + self.init_usage('test_project', 'gigabytes', 100, 0, until_refresh=5) + context = FakeContext('test_project', 'test_class') + quotas = dict(volumes=5, gigabytes=10 * 1024, ) + deltas = dict(volumes=2, gigabytes=2 * 1024, ) + self._mock_allocated_get_all_by_project() + + # Simulate service is now running with until_refresh disabled + sqa_api.quota_reserve(context, self.resources, quotas, deltas, + self.expire, None, 0) + + self.compare_usage(self.usages, [dict(resource='volumes', + project_id='test_project', + in_use=3, + reserved=2, + until_refresh=None), + dict(resource='gigabytes', + project_id='test_project', + in_use=100, + reserved=2 * 1024, + until_refresh=None), ]) + def test_quota_reserve_max_age(self): max_age = 3600 record_created = (timeutils.utcnow() - diff --git a/releasenotes/notes/quota-until_refresh-updated-d35e8530f30c5522.yaml b/releasenotes/notes/quota-until_refresh-updated-d35e8530f30c5522.yaml new file mode 100644 index 00000000000..078ccfef772 --- /dev/null +++ b/releasenotes/notes/quota-until_refresh-updated-d35e8530f30c5522.yaml @@ -0,0 +1,6 @@ +--- +fixes: + - | + `Bug #1697906 `_: Fix + ``until_refresh`` configuration changes not taking effect in a timely + fashion or at all.