Support -1 as unlimited quota restraint in Trove.
In other projects like nova and neutron, hard limit -1 often means unlimited quota restraint. But Trove dose not support that. This patch aims at two things: 1. Support -1, as unlimited quota restraint in check_quotas() 2. Add quota check to accept only -1, not -2 or other negative numbers when updating quotas. Change-Id: I028e6d7814ff240aa3f697e3d6ac8c7bac5bf3fd Closes-bug: #1729791 Signed-off-by: Fan Zhang <zh.f@outlook.com>
This commit is contained in:
parent
84af1645ac
commit
8229572c1d
|
@ -206,6 +206,12 @@ class OverLimit(TroveError):
|
||||||
"rate.")
|
"rate.")
|
||||||
|
|
||||||
|
|
||||||
|
class QuotaLimitTooSmall(TroveError):
|
||||||
|
|
||||||
|
message = _("Quota limit '%(limit)s' for '%(resource)s' is too small"
|
||||||
|
" - must be at least '-1'.")
|
||||||
|
|
||||||
|
|
||||||
class QuotaExceeded(TroveError):
|
class QuotaExceeded(TroveError):
|
||||||
|
|
||||||
message = _("Quota exceeded for resources: %(overs)s.")
|
message = _("Quota exceeded for resources: %(overs)s.")
|
||||||
|
|
|
@ -55,6 +55,9 @@ class QuotaController(wsgi.Controller):
|
||||||
for resource, limit in body['quotas'].items():
|
for resource, limit in body['quotas'].items():
|
||||||
if limit is None:
|
if limit is None:
|
||||||
continue
|
continue
|
||||||
|
elif limit < -1:
|
||||||
|
raise exception.QuotaLimitTooSmall(limit=limit,
|
||||||
|
resource=resource)
|
||||||
if resource == "xmlns":
|
if resource == "xmlns":
|
||||||
continue
|
continue
|
||||||
if resource not in registered_resources:
|
if resource not in registered_resources:
|
||||||
|
|
|
@ -147,6 +147,7 @@ class DbQuotaDriver(object):
|
||||||
|
|
||||||
overs = [resource for resource in deltas
|
overs = [resource for resource in deltas
|
||||||
if (int(deltas[resource]) > 0 and
|
if (int(deltas[resource]) > 0 and
|
||||||
|
quotas[resource].hard_limit >= 0 and
|
||||||
(quota_usages[resource].in_use +
|
(quota_usages[resource].in_use +
|
||||||
quota_usages[resource].reserved +
|
quota_usages[resource].reserved +
|
||||||
int(deltas[resource])) > quotas[resource].hard_limit)]
|
int(deltas[resource])) > quotas[resource].hard_limit)]
|
||||||
|
|
|
@ -144,6 +144,15 @@ class QuotaControllerTest(trove_testtools.TestCase):
|
||||||
self.assertEqual(200, result.status)
|
self.assertEqual(200, result.status)
|
||||||
self.assertEqual(10, result._data['quotas']['volumes'])
|
self.assertEqual(10, result._data['quotas']['volumes'])
|
||||||
|
|
||||||
|
def test_update_resource_with_invalid_negative_number(self):
|
||||||
|
quota = MagicMock(spec=Quota)
|
||||||
|
with patch.object(DatabaseModelBase, 'find_by', return_value=quota):
|
||||||
|
body = {'quotas': {'instances': -2}}
|
||||||
|
self.assertRaises(exception.QuotaLimitTooSmall,
|
||||||
|
self.controller.update,
|
||||||
|
self.req, body, FAKE_TENANT1,
|
||||||
|
FAKE_TENANT2)
|
||||||
|
|
||||||
|
|
||||||
class DbQuotaDriverTest(trove_testtools.TestCase):
|
class DbQuotaDriverTest(trove_testtools.TestCase):
|
||||||
|
|
||||||
|
@ -386,6 +395,34 @@ class DbQuotaDriverTest(trove_testtools.TestCase):
|
||||||
self.assertEqual(0, usages[Resource.VOLUMES].in_use)
|
self.assertEqual(0, usages[Resource.VOLUMES].in_use)
|
||||||
self.assertEqual(0, usages[Resource.VOLUMES].reserved)
|
self.assertEqual(0, usages[Resource.VOLUMES].reserved)
|
||||||
|
|
||||||
|
def test_check_quota_with_unlimited_quota(self):
|
||||||
|
|
||||||
|
FAKE_QUOTA_USAGE = [QuotaUsage(id=1,
|
||||||
|
tenant_id=FAKE_TENANT1,
|
||||||
|
resource=Resource.INSTANCES,
|
||||||
|
in_use=1,
|
||||||
|
reserved=2),
|
||||||
|
QuotaUsage(id=2,
|
||||||
|
tenant_id=FAKE_TENANT1,
|
||||||
|
resource=Resource.VOLUMES,
|
||||||
|
in_use=1,
|
||||||
|
reserved=1)]
|
||||||
|
FAKE_QUOTAS = [Quota(tenant_id=FAKE_TENANT1,
|
||||||
|
resource=Resource.INSTANCES,
|
||||||
|
hard_limit=-1),
|
||||||
|
Quota(tenant_id=FAKE_TENANT1,
|
||||||
|
resource=Resource.VOLUMES,
|
||||||
|
hard_limit=-1)]
|
||||||
|
|
||||||
|
self.mock_quota_result.all = Mock(return_value=FAKE_QUOTAS)
|
||||||
|
self.mock_usage_result.all = Mock(return_value=FAKE_QUOTA_USAGE)
|
||||||
|
QuotaUsage.save = Mock()
|
||||||
|
Reservation.create = Mock()
|
||||||
|
|
||||||
|
delta = {'instances': 2, 'volumes': 3}
|
||||||
|
self.assertIsNone(self.driver.check_quotas(FAKE_TENANT1, resources,
|
||||||
|
delta))
|
||||||
|
|
||||||
def test_reserve(self):
|
def test_reserve(self):
|
||||||
|
|
||||||
FAKE_QUOTAS = [QuotaUsage(id=1,
|
FAKE_QUOTAS = [QuotaUsage(id=1,
|
||||||
|
|
Loading…
Reference in New Issue