Add domain level limit support - Manager
Add the manager logic for domain level limit support. Change-Id: Iea87e8e16ca187f9da9a91a3a1aec48bc9baea10 bp: domain-level-limit
This commit is contained in:
parent
484bc96fe7
commit
347269184e
|
@ -60,6 +60,7 @@ class LimitModel(sql.ModelBase, sql.ModelDictMixin):
|
|||
'internal_id',
|
||||
'id',
|
||||
'project_id',
|
||||
'domain_id',
|
||||
'service_id',
|
||||
'region_id',
|
||||
'resource_name',
|
||||
|
@ -73,6 +74,7 @@ class LimitModel(sql.ModelBase, sql.ModelDictMixin):
|
|||
internal_id = sql.Column(sql.Integer, primary_key=True, nullable=False)
|
||||
id = sql.Column(sql.String(length=64), nullable=False, unique=True)
|
||||
project_id = sql.Column(sql.String(64))
|
||||
domain_id = sql.Column(sql.String(64))
|
||||
_service_id = sql.Column('service_id', sql.String(255))
|
||||
_region_id = sql.Column('region_id', sql.String(64), nullable=True)
|
||||
_resource_name = sql.Column('resource_name', sql.String(255))
|
||||
|
@ -159,7 +161,12 @@ class UnifiedLimit(base.UnifiedLimitDriverBase):
|
|||
query,
|
||||
hints).all()
|
||||
else:
|
||||
hints.add_filter('project_id', unified_limit['project_id'])
|
||||
is_project_limit = (True if unified_limit.get('project_id')
|
||||
else False)
|
||||
if is_project_limit:
|
||||
hints.add_filter('project_id', unified_limit['project_id'])
|
||||
else:
|
||||
hints.add_filter('domain_id', unified_limit['domain_id'])
|
||||
with sql.session_for_read() as session:
|
||||
query = session.query(LimitModel)
|
||||
old_unified_limits = sql.filter_limit_query(LimitModel,
|
||||
|
@ -167,15 +174,21 @@ class UnifiedLimit(base.UnifiedLimitDriverBase):
|
|||
hints).all()
|
||||
query = session.query(
|
||||
LimitModel).outerjoin(RegisteredLimitModel)
|
||||
new_unified_limits = query.filter(
|
||||
LimitModel.project_id ==
|
||||
unified_limit['project_id'],
|
||||
query = query.filter(
|
||||
RegisteredLimitModel.service_id ==
|
||||
unified_limit['service_id'],
|
||||
RegisteredLimitModel.region_id ==
|
||||
unified_limit.get('region_id'),
|
||||
RegisteredLimitModel.resource_name ==
|
||||
unified_limit['resource_name']).all()
|
||||
unified_limit['resource_name'])
|
||||
if is_project_limit:
|
||||
query = query.filter(
|
||||
LimitModel.project_id == unified_limit['project_id'])
|
||||
else:
|
||||
query = query.filter(
|
||||
LimitModel.domain_id == unified_limit['domain_id'])
|
||||
new_unified_limits = query.all()
|
||||
|
||||
unified_limits = old_unified_limits + new_unified_limits
|
||||
|
||||
if unified_limits:
|
||||
|
@ -315,7 +328,8 @@ class UnifiedLimit(base.UnifiedLimitDriverBase):
|
|||
hints)
|
||||
old_format_data = [s.to_dict() for s in limits]
|
||||
project_filter = hint_copy.get_exact_filter_by_name('project_id')
|
||||
if hint_copy.filters and (not project_filter
|
||||
domain_filter = hint_copy.get_exact_filter_by_name('domain_id')
|
||||
if hint_copy.filters and (not (project_filter or domain_filter)
|
||||
or len(hint_copy.filters) > 1):
|
||||
# If the hints contain "service_id", "region_id" or
|
||||
# "resource_name", we should combine the registered_limit table
|
||||
|
@ -328,6 +342,9 @@ class UnifiedLimit(base.UnifiedLimitDriverBase):
|
|||
if project_filter:
|
||||
limits = limits.filter(
|
||||
LimitModel.project_id == project_filter['value'])
|
||||
elif domain_filter:
|
||||
limits = limits.filter(
|
||||
LimitModel.domain_id == domain_filter['value'])
|
||||
new_format_data = [s.to_dict() for s in limits]
|
||||
return old_format_data + new_format_data
|
||||
|
||||
|
|
|
@ -55,10 +55,14 @@ class Manager(manager.Manager):
|
|||
project_id = unified_limit.get('project_id')
|
||||
if project_id is not None:
|
||||
project = PROVIDERS.resource_api.get_project(project_id)
|
||||
# Keystone now does not support domain-level limits. This
|
||||
# check can be removed if it'll be supported in the future.
|
||||
if project['is_domain']:
|
||||
raise exception.ProjectNotFound(project_id=project_id)
|
||||
# Treat the input limit as domain level limit.
|
||||
unified_limit['domain_id'] = unified_limit.pop(
|
||||
'project_id')
|
||||
domain_id = unified_limit.get('domain_id')
|
||||
if domain_id is not None:
|
||||
PROVIDERS.resource_api.get_domain(domain_id)
|
||||
|
||||
except exception.ServiceNotFound:
|
||||
raise exception.ValidationError(attribute='service_id',
|
||||
target=target)
|
||||
|
@ -68,6 +72,9 @@ class Manager(manager.Manager):
|
|||
except exception.ProjectNotFound:
|
||||
raise exception.ValidationError(attribute='project_id',
|
||||
target=target)
|
||||
except exception.DomainNotFound:
|
||||
raise exception.ValidationError(attribute='domain_id',
|
||||
target=target)
|
||||
|
||||
def get_model(self):
|
||||
"""Return information of the configured enforcement model."""
|
||||
|
|
|
@ -408,14 +408,15 @@ class LimitTests(object):
|
|||
enforcement_model=uuid.uuid4().hex
|
||||
)
|
||||
|
||||
def test_create_limit(self):
|
||||
def test_create_project_limit(self):
|
||||
# create one, return it.
|
||||
limit_1 = unit.new_limit_ref(
|
||||
project_id=self.project_bar['id'],
|
||||
service_id=self.service_one['id'],
|
||||
region_id=self.region_one['id'],
|
||||
resource_name='volume', resource_limit=10, id=uuid.uuid4().hex,
|
||||
description='test description')
|
||||
description='test description',
|
||||
domain_id=None)
|
||||
limits = PROVIDERS.unified_limit_api.create_limits([limit_1])
|
||||
self.assertDictEqual(limit_1, limits[0])
|
||||
|
||||
|
@ -424,12 +425,14 @@ class LimitTests(object):
|
|||
project_id=self.project_bar['id'],
|
||||
service_id=self.service_one['id'],
|
||||
region_id=self.region_two['id'],
|
||||
resource_name='snapshot', resource_limit=5, id=uuid.uuid4().hex)
|
||||
resource_name='snapshot', resource_limit=5, id=uuid.uuid4().hex,
|
||||
domain_id=None)
|
||||
limit_3 = unit.new_limit_ref(
|
||||
project_id=self.project_bar['id'],
|
||||
service_id=self.service_one['id'],
|
||||
region_id=self.region_two['id'],
|
||||
resource_name='backup', resource_limit=5, id=uuid.uuid4().hex)
|
||||
resource_name='backup', resource_limit=5, id=uuid.uuid4().hex,
|
||||
domain_id=None)
|
||||
|
||||
limits = PROVIDERS.unified_limit_api.create_limits([limit_2, limit_3])
|
||||
for limit in limits:
|
||||
|
@ -438,7 +441,18 @@ class LimitTests(object):
|
|||
if limit['id'] == limit_3['id']:
|
||||
self.assertDictEqual(limit_3, limit)
|
||||
|
||||
def test_create_limit_duplicate(self):
|
||||
def test_create_domain_limit(self):
|
||||
limit_1 = unit.new_limit_ref(
|
||||
project_id=None,
|
||||
service_id=self.service_one['id'],
|
||||
region_id=self.region_one['id'],
|
||||
resource_name='volume', resource_limit=10, id=uuid.uuid4().hex,
|
||||
description='test description',
|
||||
domain_id=self.domain_default['id'])
|
||||
limits = PROVIDERS.unified_limit_api.create_limits([limit_1])
|
||||
self.assertDictEqual(limit_1, limits[0])
|
||||
|
||||
def test_create_project_limit_duplicate(self):
|
||||
limit_1 = unit.new_limit_ref(
|
||||
project_id=self.project_bar['id'],
|
||||
service_id=self.service_one['id'],
|
||||
|
@ -456,6 +470,26 @@ class LimitTests(object):
|
|||
PROVIDERS.unified_limit_api.create_limits,
|
||||
[limit_1])
|
||||
|
||||
def test_create_domain_limit_duplicate(self):
|
||||
limit_1 = unit.new_limit_ref(
|
||||
project_id=None,
|
||||
service_id=self.service_one['id'],
|
||||
region_id=self.region_one['id'],
|
||||
resource_name='volume', resource_limit=10, id=uuid.uuid4().hex,
|
||||
domain_id=self.domain_default['id'])
|
||||
PROVIDERS.unified_limit_api.create_limits([limit_1])
|
||||
|
||||
# use different id but the same domain_id, service_id and region_id
|
||||
limit_1 = unit.new_limit_ref(
|
||||
project_id=None,
|
||||
service_id=self.service_one['id'],
|
||||
region_id=self.region_one['id'],
|
||||
resource_name='volume', resource_limit=10, id=uuid.uuid4().hex,
|
||||
domain_id=self.domain_default['id'])
|
||||
self.assertRaises(exception.Conflict,
|
||||
PROVIDERS.unified_limit_api.create_limits,
|
||||
[limit_1])
|
||||
|
||||
def test_create_limit_with_invalid_service_raises_validation_error(self):
|
||||
limit = unit.new_limit_ref(
|
||||
project_id=self.project_bar['id'],
|
||||
|
@ -539,12 +573,14 @@ class LimitTests(object):
|
|||
project_id=self.project_bar['id'],
|
||||
service_id=self.service_one['id'],
|
||||
region_id=self.region_one['id'],
|
||||
resource_name='volume', resource_limit=10, id=uuid.uuid4().hex)
|
||||
resource_name='volume', resource_limit=10, id=uuid.uuid4().hex,
|
||||
domain_id=None)
|
||||
limit_2 = unit.new_limit_ref(
|
||||
project_id=self.project_bar['id'],
|
||||
service_id=self.service_one['id'],
|
||||
region_id=self.region_two['id'],
|
||||
resource_name='snapshot', resource_limit=5, id=uuid.uuid4().hex)
|
||||
resource_name='snapshot', resource_limit=5, id=uuid.uuid4().hex,
|
||||
domain_id=None)
|
||||
PROVIDERS.unified_limit_api.create_limits([limit_1, limit_2])
|
||||
|
||||
# list
|
||||
|
@ -565,12 +601,14 @@ class LimitTests(object):
|
|||
project_id=self.project_bar['id'],
|
||||
service_id=self.service_one['id'],
|
||||
region_id=self.region_one['id'],
|
||||
resource_name='volume', resource_limit=10, id=uuid.uuid4().hex)
|
||||
resource_name='volume', resource_limit=10, id=uuid.uuid4().hex,
|
||||
domain_id=None)
|
||||
limit_2 = unit.new_limit_ref(
|
||||
project_id=self.project_bar['id'],
|
||||
service_id=self.service_one['id'],
|
||||
region_id=self.region_two['id'],
|
||||
resource_name='snapshot', resource_limit=5, id=uuid.uuid4().hex)
|
||||
resource_name='snapshot', resource_limit=5, id=uuid.uuid4().hex,
|
||||
domain_id=None)
|
||||
PROVIDERS.unified_limit_api.create_limits([limit_1, limit_2])
|
||||
|
||||
# list, limit is 1
|
||||
|
@ -587,18 +625,26 @@ class LimitTests(object):
|
|||
project_id=self.project_bar['id'],
|
||||
service_id=self.service_one['id'],
|
||||
region_id=self.region_one['id'],
|
||||
resource_name='volume', resource_limit=10, id=uuid.uuid4().hex)
|
||||
resource_name='volume', resource_limit=10, id=uuid.uuid4().hex,
|
||||
domain_id=None)
|
||||
limit_2 = unit.new_limit_ref(
|
||||
project_id=self.project_baz['id'],
|
||||
service_id=self.service_one['id'],
|
||||
region_id=self.region_two['id'],
|
||||
resource_name='snapshot', resource_limit=10, id=uuid.uuid4().hex)
|
||||
PROVIDERS.unified_limit_api.create_limits([limit_1, limit_2])
|
||||
resource_name='snapshot', resource_limit=10, id=uuid.uuid4().hex,
|
||||
domain_id=None)
|
||||
limit_3 = unit.new_limit_ref(
|
||||
project_id=None,
|
||||
service_id=self.service_one['id'],
|
||||
region_id=self.region_two['id'],
|
||||
resource_name='snapshot', resource_limit=10, id=uuid.uuid4().hex,
|
||||
domain_id=self.domain_default['id'])
|
||||
PROVIDERS.unified_limit_api.create_limits([limit_1, limit_2, limit_3])
|
||||
|
||||
hints = driver_hints.Hints()
|
||||
hints.add_filter('service_id', self.service_one['id'])
|
||||
res = PROVIDERS.unified_limit_api.list_limits(hints)
|
||||
self.assertEqual(2, len(res))
|
||||
self.assertEqual(3, len(res))
|
||||
|
||||
hints = driver_hints.Hints()
|
||||
hints.add_filter('region_id', self.region_one['id'])
|
||||
|
@ -616,6 +662,11 @@ class LimitTests(object):
|
|||
res = PROVIDERS.unified_limit_api.list_limits(hints)
|
||||
self.assertEqual(1, len(res))
|
||||
|
||||
hints = driver_hints.Hints()
|
||||
hints.add_filter('domain_id', self.domain_default['id'])
|
||||
res = PROVIDERS.unified_limit_api.list_limits(hints)
|
||||
self.assertEqual(1, len(res))
|
||||
|
||||
def test_list_limit_by_multi_filter_with_project_id(self):
|
||||
limit_1 = unit.new_limit_ref(
|
||||
project_id=self.project_bar['id'],
|
||||
|
@ -641,12 +692,14 @@ class LimitTests(object):
|
|||
project_id=self.project_bar['id'],
|
||||
service_id=self.service_one['id'],
|
||||
region_id=self.region_one['id'],
|
||||
resource_name='volume', resource_limit=10, id=uuid.uuid4().hex)
|
||||
resource_name='volume', resource_limit=10, id=uuid.uuid4().hex,
|
||||
domain_id=None)
|
||||
limit_2 = unit.new_limit_ref(
|
||||
project_id=self.project_bar['id'],
|
||||
service_id=self.service_one['id'],
|
||||
region_id=self.region_two['id'],
|
||||
resource_name='snapshot', resource_limit=5, id=uuid.uuid4().hex)
|
||||
resource_name='snapshot', resource_limit=5, id=uuid.uuid4().hex,
|
||||
domain_id=None)
|
||||
PROVIDERS.unified_limit_api.create_limits([limit_1, limit_2])
|
||||
|
||||
# show one
|
||||
|
|
|
@ -657,11 +657,11 @@ class LimitsTestCase(test_v3.RestfulTestCase):
|
|||
service_id=self.service_id,
|
||||
region_id=self.region_id,
|
||||
resource_name='volume')
|
||||
self.post(
|
||||
'/limits',
|
||||
body={'limits': [ref]},
|
||||
token=self.system_admin_token,
|
||||
expected_status=http_client.BAD_REQUEST)
|
||||
r = self.post('/limits', body={'limits': [ref]},
|
||||
token=self.system_admin_token)
|
||||
limits = r.result['limits']
|
||||
self.assertIsNone(limits[0]['project_id'])
|
||||
self.assertEqual(self.domain_id, limits[0]['domain_id'])
|
||||
|
||||
def test_create_multi_limit(self):
|
||||
ref1 = unit.new_limit_ref(project_id=self.project_id,
|
||||
|
@ -1524,3 +1524,7 @@ class StrictTwoLevelLimitsTestCase(LimitsTestCase):
|
|||
body={'limit': update_dict},
|
||||
token=self.system_admin_token,
|
||||
expected_status=http_client.FORBIDDEN)
|
||||
|
||||
def test_create_limit_with_domain_as_project(self):
|
||||
self.skipTest('enable this test once strict two level model support'
|
||||
'domain level check.')
|
||||
|
|
Loading…
Reference in New Issue