api: Add response body schemas for limits API
Change-Id: Iec1c43dc2ee34488afd337eb65f4245def460e16 Signed-off-by: Stephen Finucane <stephenfin@redhat.com>
This commit is contained in:
@@ -14,7 +14,7 @@
|
||||
# under the License.
|
||||
|
||||
from nova.api.openstack import api_version_request
|
||||
from nova.api.openstack.compute.schemas import limits
|
||||
from nova.api.openstack.compute.schemas import limits as schema
|
||||
from nova.api.openstack.compute.views import limits as limits_views
|
||||
from nova.api.openstack import wsgi
|
||||
from nova.api import validation
|
||||
@@ -27,26 +27,32 @@ QUOTAS = quota.QUOTAS
|
||||
# This is a list of limits which needs to filter out from the API response.
|
||||
# This is due to the deprecation of network related proxy APIs, the related
|
||||
# limit should be removed from the API also.
|
||||
FILTERED_LIMITS_2_36 = ['floating_ips', 'security_groups',
|
||||
'security_group_rules']
|
||||
FILTERED_LIMITS_v236 = [
|
||||
'floating_ips', 'security_groups', 'security_group_rules'
|
||||
]
|
||||
|
||||
FILTERED_LIMITS_2_57 = list(FILTERED_LIMITS_2_36)
|
||||
FILTERED_LIMITS_2_57.extend(['injected_files', 'injected_file_content_bytes'])
|
||||
FILTERED_LIMITS_v257 = list(FILTERED_LIMITS_v236)
|
||||
FILTERED_LIMITS_v257.extend(['injected_files', 'injected_file_content_bytes'])
|
||||
|
||||
|
||||
@validation.validated
|
||||
class LimitsController(wsgi.Controller):
|
||||
"""Controller for accessing limits in the OpenStack API."""
|
||||
|
||||
@wsgi.expected_errors(())
|
||||
@validation.query_schema(limits.limits_query_schema, '2.1', '2.56')
|
||||
@validation.query_schema(limits.limits_query_schema, '2.57', '2.74')
|
||||
@validation.query_schema(limits.limits_query_schema_275, '2.75')
|
||||
@validation.query_schema(schema.index_query, '2.1', '2.56')
|
||||
@validation.query_schema(schema.index_query, '2.57', '2.74')
|
||||
@validation.query_schema(schema.index_query_v275, '2.75')
|
||||
@validation.response_body_schema(schema.index_response, '2.1', '2.35')
|
||||
@validation.response_body_schema(schema.index_response_v236, '2.36', '2.38') # noqa: E501
|
||||
@validation.response_body_schema(schema.index_response_v239, '2.39', '2.56') # noqa: E501
|
||||
@validation.response_body_schema(schema.index_response_v257, '2.57')
|
||||
def index(self, req):
|
||||
filtered_limits = []
|
||||
if api_version_request.is_supported(req, '2.57'):
|
||||
filtered_limits = FILTERED_LIMITS_2_57
|
||||
filtered_limits = FILTERED_LIMITS_v257
|
||||
elif api_version_request.is_supported(req, '2.36'):
|
||||
filtered_limits = FILTERED_LIMITS_2_36
|
||||
filtered_limits = FILTERED_LIMITS_v236
|
||||
|
||||
max_image_meta = True
|
||||
if api_version_request.is_supported(req, '2.39'):
|
||||
|
||||
@@ -16,7 +16,7 @@ import copy
|
||||
from nova.api.validation import parameter_types
|
||||
|
||||
|
||||
limits_query_schema = {
|
||||
index_query = {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'tenant_id': parameter_types.common_query_param,
|
||||
@@ -27,5 +27,128 @@ limits_query_schema = {
|
||||
'additionalProperties': True
|
||||
}
|
||||
|
||||
limits_query_schema_275 = copy.deepcopy(limits_query_schema)
|
||||
limits_query_schema_275['additionalProperties'] = False
|
||||
index_query_v275 = copy.deepcopy(index_query)
|
||||
index_query_v275['additionalProperties'] = False
|
||||
|
||||
_absolute_quota_response = {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'maxImageMeta': {'type': 'integer', 'minimum': -1},
|
||||
'maxPersonality': {'type': 'integer', 'minimum': -1},
|
||||
'maxPersonalitySize': {'type': 'integer', 'minimum': -1},
|
||||
'maxSecurityGroups': {'type': 'integer', 'minimum': -1},
|
||||
'maxSecurityGroupRules': {'type': 'integer', 'minimum': -1},
|
||||
'maxServerMeta': {'type': 'integer', 'minimum': -1},
|
||||
'maxServerGroups': {'type': 'integer', 'minimum': -1},
|
||||
'maxServerGroupMembers': {'type': 'integer', 'minimum': -1},
|
||||
'maxTotalCores': {'type': 'integer', 'minimum': -1},
|
||||
'maxTotalFloatingIps': {'type': 'integer', 'minimum': -1},
|
||||
'maxTotalInstances': {'type': 'integer', 'minimum': -1},
|
||||
'maxTotalKeypairs': {'type': 'integer', 'minimum': -1},
|
||||
'maxTotalRAMSize': {'type': 'integer', 'minimum': -1},
|
||||
'totalCoresUsed': {'type': 'integer', 'minimum': -1},
|
||||
'totalFloatingIpsUsed': {'type': 'integer', 'minimum': -1},
|
||||
'totalInstancesUsed': {'type': 'integer', 'minimum': -1},
|
||||
'totalRAMUsed': {'type': 'integer', 'minimum': -1},
|
||||
'totalSecurityGroupsUsed': {'type': 'integer', 'minimum': -1},
|
||||
'totalServerGroupsUsed': {'type': 'integer', 'minimum': -1},
|
||||
},
|
||||
'required': [
|
||||
'maxImageMeta',
|
||||
'maxPersonality',
|
||||
'maxPersonalitySize',
|
||||
'maxSecurityGroups',
|
||||
'maxSecurityGroupRules',
|
||||
'maxServerMeta',
|
||||
'maxServerGroups',
|
||||
'maxServerGroupMembers',
|
||||
'maxTotalCores',
|
||||
'maxTotalFloatingIps',
|
||||
'maxTotalInstances',
|
||||
'maxTotalKeypairs',
|
||||
'maxTotalRAMSize',
|
||||
'totalCoresUsed',
|
||||
'totalFloatingIpsUsed',
|
||||
'totalInstancesUsed',
|
||||
'totalRAMUsed',
|
||||
'totalSecurityGroupsUsed',
|
||||
'totalServerGroupsUsed',
|
||||
],
|
||||
'additionalProperties': False,
|
||||
}
|
||||
|
||||
_absolute_quota_response_v236 = copy.deepcopy(_absolute_quota_response)
|
||||
del _absolute_quota_response_v236['properties']['maxSecurityGroups']
|
||||
del _absolute_quota_response_v236['properties']['maxSecurityGroupRules']
|
||||
del _absolute_quota_response_v236['properties']['maxTotalFloatingIps']
|
||||
del _absolute_quota_response_v236['properties']['totalFloatingIpsUsed']
|
||||
del _absolute_quota_response_v236['properties']['totalSecurityGroupsUsed']
|
||||
_absolute_quota_response_v236['required'].pop(
|
||||
_absolute_quota_response_v236['required'].index('maxSecurityGroups')
|
||||
)
|
||||
_absolute_quota_response_v236['required'].pop(
|
||||
_absolute_quota_response_v236['required'].index('maxSecurityGroupRules')
|
||||
)
|
||||
_absolute_quota_response_v236['required'].pop(
|
||||
_absolute_quota_response_v236['required'].index('maxTotalFloatingIps')
|
||||
)
|
||||
_absolute_quota_response_v236['required'].pop(
|
||||
_absolute_quota_response_v236['required'].index('totalFloatingIpsUsed')
|
||||
)
|
||||
_absolute_quota_response_v236['required'].pop(
|
||||
_absolute_quota_response_v236['required'].index('totalSecurityGroupsUsed')
|
||||
)
|
||||
|
||||
_absolute_quota_response_v239 = copy.deepcopy(_absolute_quota_response_v236)
|
||||
del _absolute_quota_response_v239['properties']['maxImageMeta']
|
||||
_absolute_quota_response_v239['required'].pop(
|
||||
_absolute_quota_response_v239['required'].index('maxImageMeta')
|
||||
)
|
||||
|
||||
_absolute_quota_response_v257 = copy.deepcopy(_absolute_quota_response_v239)
|
||||
del _absolute_quota_response_v257['properties']['maxPersonality']
|
||||
del _absolute_quota_response_v257['properties']['maxPersonalitySize']
|
||||
_absolute_quota_response_v257['required'].pop(
|
||||
_absolute_quota_response_v257['required'].index('maxPersonality')
|
||||
)
|
||||
_absolute_quota_response_v257['required'].pop(
|
||||
_absolute_quota_response_v257['required'].index('maxPersonalitySize')
|
||||
)
|
||||
|
||||
index_response = {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'limits': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'absolute': _absolute_quota_response,
|
||||
'rate': {
|
||||
'type': 'array',
|
||||
# Yes, this is an empty array
|
||||
'items': {},
|
||||
'maxItems': 0,
|
||||
'additionalItems': False,
|
||||
},
|
||||
},
|
||||
'required': ['absolute', 'rate'],
|
||||
'additionalProperties': False,
|
||||
},
|
||||
},
|
||||
'required': ['limits'],
|
||||
'additionalProperties': False,
|
||||
}
|
||||
|
||||
index_response_v236 = copy.deepcopy(index_response)
|
||||
index_response_v236['properties']['limits']['properties']['absolute'] = (
|
||||
_absolute_quota_response_v236
|
||||
)
|
||||
|
||||
index_response_v239 = copy.deepcopy(index_response)
|
||||
index_response_v239['properties']['limits']['properties']['absolute'] = (
|
||||
_absolute_quota_response_v239
|
||||
)
|
||||
|
||||
index_response_v257 = copy.deepcopy(index_response_v236)
|
||||
index_response_v257['properties']['limits']['properties']['absolute'] = (
|
||||
_absolute_quota_response_v257
|
||||
)
|
||||
|
||||
@@ -33,7 +33,7 @@ class ViewBuilder(object):
|
||||
"security_group_rules": ["maxSecurityGroupRules"],
|
||||
"server_groups": ["maxServerGroups"],
|
||||
"server_group_members": ["maxServerGroupMembers"]
|
||||
}
|
||||
}
|
||||
|
||||
def build(self, request, quotas, filtered_limits=None,
|
||||
max_image_meta=True):
|
||||
|
||||
@@ -1418,22 +1418,22 @@ def _server_group_count(context, project_id, user_id=None):
|
||||
|
||||
QUOTAS = QuotaEngine(
|
||||
resources=[
|
||||
CountableResource(
|
||||
'instances', _instances_cores_ram_count, 'instances'),
|
||||
CountableResource(
|
||||
'cores', _instances_cores_ram_count, 'cores'),
|
||||
CountableResource(
|
||||
'ram', _instances_cores_ram_count, 'ram'),
|
||||
AbsoluteResource(
|
||||
'metadata_items', 'metadata_items'),
|
||||
AbsoluteResource(
|
||||
'injected_files', 'injected_files'),
|
||||
AbsoluteResource(
|
||||
'injected_file_content_bytes', 'injected_file_content_bytes'),
|
||||
AbsoluteResource(
|
||||
'injected_file_path_bytes', 'injected_file_path_length'),
|
||||
CountableResource(
|
||||
'instances', _instances_cores_ram_count, 'instances'),
|
||||
CountableResource(
|
||||
'key_pairs', _keypair_get_count_by_user, 'key_pairs'),
|
||||
AbsoluteResource(
|
||||
'metadata_items', 'metadata_items'),
|
||||
CountableResource(
|
||||
'ram', _instances_cores_ram_count, 'ram'),
|
||||
CountableResource(
|
||||
'server_groups', _server_group_count, 'server_groups'),
|
||||
CountableResource(
|
||||
|
||||
@@ -39,22 +39,40 @@ from nova.tests.unit.api.openstack import fakes
|
||||
from nova.tests.unit import matchers
|
||||
|
||||
|
||||
def fake_get_project_quotas(context, project_id, usages=True):
|
||||
absolute_limits = {
|
||||
'cores': -1,
|
||||
'floating_ips': 10,
|
||||
'injected_files': -1,
|
||||
'injected_file_content_bytes': -1,
|
||||
'injected_file_path_bytes': -1,
|
||||
'instances': 5,
|
||||
'key_pairs': -1,
|
||||
'metadata_items': -1,
|
||||
'ram': 512,
|
||||
'server_groups': 10,
|
||||
'server_group_members': -1,
|
||||
'security_groups': 10,
|
||||
'security_group_rules': 20,
|
||||
}
|
||||
|
||||
return {
|
||||
k: {'limit': v, 'in_use': v // 2}
|
||||
for k, v in absolute_limits.items()
|
||||
}
|
||||
|
||||
|
||||
class BaseLimitTestSuite(test.NoDBTestCase):
|
||||
"""Base test suite which provides relevant stubs and time abstraction."""
|
||||
|
||||
def setUp(self):
|
||||
super(BaseLimitTestSuite, self).setUp()
|
||||
super().setUp()
|
||||
self.time = 0.0
|
||||
self.absolute_limits = {}
|
||||
|
||||
def stub_get_project_quotas(context, project_id, usages=True):
|
||||
return {k: dict(limit=v, in_use=v // 2)
|
||||
for k, v in self.absolute_limits.items()}
|
||||
|
||||
patcher_get_project_quotas = mock.patch.object(
|
||||
nova.quota.QUOTAS,
|
||||
"get_project_quotas",
|
||||
side_effect=stub_get_project_quotas)
|
||||
side_effect=fake_get_project_quotas)
|
||||
self.mock_get_project_quotas = patcher_get_project_quotas.start()
|
||||
self.addCleanup(patcher_get_project_quotas.stop)
|
||||
patcher = self.mock_can = mock.patch('nova.context.RequestContext.can')
|
||||
@@ -94,19 +112,6 @@ class LimitsControllerTestV21(BaseLimitTestSuite):
|
||||
request.environ["nova.context"] = context
|
||||
return request
|
||||
|
||||
def test_empty_index_json(self):
|
||||
# Test getting empty limit details in JSON.
|
||||
request = self._get_index_request()
|
||||
response = request.get_response(self.controller)
|
||||
expected = {
|
||||
"limits": {
|
||||
"rate": [],
|
||||
"absolute": {},
|
||||
},
|
||||
}
|
||||
body = jsonutils.loads(response.body)
|
||||
self.assertEqual(expected, body)
|
||||
|
||||
def test_index_json(self):
|
||||
self._test_index_json()
|
||||
|
||||
@@ -120,41 +125,33 @@ class LimitsControllerTestV21(BaseLimitTestSuite):
|
||||
if tenant_id is None:
|
||||
tenant_id = context.project_id
|
||||
|
||||
self.absolute_limits = {
|
||||
'ram': 512,
|
||||
'instances': 5,
|
||||
'cores': 21,
|
||||
'key_pairs': 10,
|
||||
'floating_ips': 10,
|
||||
'security_groups': 10,
|
||||
'security_group_rules': 20,
|
||||
}
|
||||
expected = {
|
||||
"limits": {
|
||||
"rate": [],
|
||||
"absolute": {
|
||||
"maxTotalRAMSize": 512,
|
||||
"maxTotalInstances": 5,
|
||||
"maxTotalCores": 21,
|
||||
"maxTotalKeypairs": 10,
|
||||
"maxTotalFloatingIps": 10,
|
||||
"maxImageMeta": -1,
|
||||
"maxPersonality": -1,
|
||||
"maxPersonalitySize": -1,
|
||||
"maxSecurityGroups": 10,
|
||||
"maxSecurityGroupRules": 20,
|
||||
"totalRAMUsed": 256,
|
||||
"totalCoresUsed": 10,
|
||||
"totalInstancesUsed": 2,
|
||||
"maxServerGroups": 10,
|
||||
"maxServerGroupMembers": -1,
|
||||
"maxServerMeta": -1,
|
||||
"maxTotalCores": -1,
|
||||
"maxTotalFloatingIps": 10,
|
||||
"maxTotalInstances": 5,
|
||||
"maxTotalKeypairs": -1,
|
||||
"maxTotalRAMSize": 512,
|
||||
"totalCoresUsed": -1,
|
||||
"totalFloatingIpsUsed": 5,
|
||||
"totalInstancesUsed": 2,
|
||||
"totalRAMUsed": 256,
|
||||
"totalSecurityGroupsUsed": 5,
|
||||
},
|
||||
"totalServerGroupsUsed": 5,
|
||||
},
|
||||
"rate": [],
|
||||
},
|
||||
}
|
||||
|
||||
def _get_project_quotas(context, project_id, usages=True):
|
||||
return {k: dict(limit=v, in_use=v // 2)
|
||||
for k, v in self.absolute_limits.items()}
|
||||
|
||||
self.mock_get_project_quotas.side_effect = _get_project_quotas
|
||||
|
||||
response = request.get_response(self.controller)
|
||||
|
||||
body = jsonutils.loads(response.body)
|
||||
@@ -162,43 +159,6 @@ class LimitsControllerTestV21(BaseLimitTestSuite):
|
||||
self.mock_get_project_quotas.assert_called_once_with(
|
||||
context, tenant_id, usages=True)
|
||||
|
||||
def _do_test_used_limits(self, reserved):
|
||||
request = self._get_index_request(tenant_id=None)
|
||||
quota_map = {
|
||||
'totalRAMUsed': 'ram',
|
||||
'totalCoresUsed': 'cores',
|
||||
'totalInstancesUsed': 'instances',
|
||||
'totalFloatingIpsUsed': 'floating_ips',
|
||||
'totalSecurityGroupsUsed': 'security_groups',
|
||||
'totalServerGroupsUsed': 'server_groups',
|
||||
}
|
||||
limits = {}
|
||||
expected_abs_limits = []
|
||||
for display_name, q in quota_map.items():
|
||||
limits[q] = {'limit': len(display_name),
|
||||
'in_use': len(display_name) // 2,
|
||||
'reserved': 0}
|
||||
expected_abs_limits.append(display_name)
|
||||
|
||||
def stub_get_project_quotas(context, project_id, usages=True):
|
||||
return limits
|
||||
|
||||
self.mock_get_project_quotas.side_effect = stub_get_project_quotas
|
||||
|
||||
res = request.get_response(self.controller)
|
||||
body = jsonutils.loads(res.body)
|
||||
abs_limits = body['limits']['absolute']
|
||||
for limit in expected_abs_limits:
|
||||
value = abs_limits[limit]
|
||||
r = limits[quota_map[limit]]['reserved'] if reserved else 0
|
||||
self.assertEqual(limits[quota_map[limit]]['in_use'] + r, value)
|
||||
|
||||
def test_used_limits_basic(self):
|
||||
self._do_test_used_limits(False)
|
||||
|
||||
def test_used_limits_with_reserved(self):
|
||||
self._do_test_used_limits(True)
|
||||
|
||||
def test_admin_can_fetch_limits_for_a_given_tenant_id(self):
|
||||
project_id = "123456"
|
||||
user_id = "A1234"
|
||||
@@ -214,8 +174,8 @@ class LimitsControllerTestV21(BaseLimitTestSuite):
|
||||
self.assertEqual(2, self.mock_can.call_count)
|
||||
self.mock_can.assert_called_with(
|
||||
l_policies.OTHER_PROJECT_LIMIT_POLICY_NAME)
|
||||
self.mock_get_project_quotas.assert_called_once_with(context,
|
||||
tenant_id, usages=True)
|
||||
self.mock_get_project_quotas.assert_called_once_with(
|
||||
context, tenant_id, usages=True)
|
||||
|
||||
def _test_admin_can_fetch_used_limits_for_own_project(self, req_get):
|
||||
project_id = "123456"
|
||||
@@ -268,33 +228,6 @@ class LimitsControllerTestV21(BaseLimitTestSuite):
|
||||
self.mock_get_project_quotas.assert_called_once_with(
|
||||
context, project_id, usages=True)
|
||||
|
||||
def test_used_ram_added(self):
|
||||
fake_req = self._get_index_request()
|
||||
|
||||
def stub_get_project_quotas(context, project_id, usages=True):
|
||||
return {'ram': {'limit': 512, 'in_use': 256}}
|
||||
|
||||
self.mock_get_project_quotas.side_effect = stub_get_project_quotas
|
||||
|
||||
res = fake_req.get_response(self.controller)
|
||||
body = jsonutils.loads(res.body)
|
||||
abs_limits = body['limits']['absolute']
|
||||
self.assertIn('totalRAMUsed', abs_limits)
|
||||
self.assertEqual(256, abs_limits['totalRAMUsed'])
|
||||
self.assertEqual(1, self.mock_get_project_quotas.call_count)
|
||||
|
||||
def test_no_ram_quota(self):
|
||||
fake_req = self._get_index_request()
|
||||
|
||||
self.mock_get_project_quotas.side_effect = None
|
||||
self.mock_get_project_quotas.return_value = {}
|
||||
|
||||
res = fake_req.get_response(self.controller)
|
||||
body = jsonutils.loads(res.body)
|
||||
abs_limits = body['limits']['absolute']
|
||||
self.assertNotIn('totalRAMUsed', abs_limits)
|
||||
self.assertEqual(1, self.mock_get_project_quotas.call_count)
|
||||
|
||||
|
||||
class FakeHttplibSocket(object):
|
||||
"""Fake `httplib.HTTPResponse` replacement."""
|
||||
@@ -346,28 +279,32 @@ class LimitsViewBuilderTest(test.NoDBTestCase):
|
||||
super(LimitsViewBuilderTest, self).setUp()
|
||||
self.view_builder = views.limits.ViewBuilder()
|
||||
self.req = fakes.HTTPRequest.blank('/?tenant_id=None')
|
||||
self.rate_limits = []
|
||||
self.absolute_limits = {"metadata_items": {'limit': 1, 'in_use': 1},
|
||||
"injected_files": {'limit': 5, 'in_use': 1},
|
||||
"injected_file_content_bytes":
|
||||
{'limit': 5, 'in_use': 1}}
|
||||
|
||||
def test_build_limits(self):
|
||||
expected_limits = {"limits": {
|
||||
quotas = {
|
||||
"metadata_items": {'limit': 1, 'in_use': 1},
|
||||
"injected_files": {'limit': 5, 'in_use': 1},
|
||||
"injected_file_content_bytes": {'limit': 5, 'in_use': 1},
|
||||
}
|
||||
expected_limits = {
|
||||
"limits": {
|
||||
"rate": [],
|
||||
"absolute": {"maxServerMeta": 1,
|
||||
"maxImageMeta": 1,
|
||||
"maxPersonality": 5,
|
||||
"maxPersonalitySize": 5}}}
|
||||
"absolute": {
|
||||
"maxServerMeta": 1,
|
||||
"maxImageMeta": 1,
|
||||
"maxPersonality": 5,
|
||||
"maxPersonalitySize": 5,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
output = self.view_builder.build(self.req, self.absolute_limits)
|
||||
output = self.view_builder.build(self.req, quotas)
|
||||
self.assertThat(output, matchers.DictMatches(expected_limits))
|
||||
|
||||
def test_build_limits_empty_limits(self):
|
||||
expected_limits = {"limits": {"rate": [],
|
||||
"absolute": {}}}
|
||||
|
||||
quotas = {}
|
||||
expected_limits = {"limits": {"rate": [], "absolute": {}}}
|
||||
|
||||
output = self.view_builder.build(self.req, quotas)
|
||||
self.assertThat(output, matchers.DictMatches(expected_limits))
|
||||
|
||||
@@ -381,34 +318,25 @@ class LimitsControllerTestV236(BaseLimitTestSuite):
|
||||
version='2.36')
|
||||
|
||||
def test_index_filtered(self):
|
||||
absolute_limits = {
|
||||
'ram': 512,
|
||||
'instances': 5,
|
||||
'cores': 21,
|
||||
'key_pairs': 10,
|
||||
'floating_ips': 10,
|
||||
'security_groups': 10,
|
||||
'security_group_rules': 20,
|
||||
}
|
||||
|
||||
def _get_project_quotas(context, project_id, usages=True):
|
||||
return {k: dict(limit=v, in_use=v // 2)
|
||||
for k, v in absolute_limits.items()}
|
||||
|
||||
self.mock_get_project_quotas.side_effect = _get_project_quotas
|
||||
|
||||
response = self.controller.index(self.req)
|
||||
expected_response = {
|
||||
"limits": {
|
||||
"rate": [],
|
||||
"absolute": {
|
||||
"maxTotalRAMSize": 512,
|
||||
"maxImageMeta": -1,
|
||||
"maxPersonality": -1,
|
||||
"maxPersonalitySize": -1,
|
||||
"maxServerGroups": 10,
|
||||
"maxServerGroupMembers": -1,
|
||||
"maxServerMeta": -1,
|
||||
"maxTotalCores": -1,
|
||||
"maxTotalInstances": 5,
|
||||
"maxTotalCores": 21,
|
||||
"maxTotalKeypairs": 10,
|
||||
"totalRAMUsed": 256,
|
||||
"totalCoresUsed": 10,
|
||||
"maxTotalKeypairs": -1,
|
||||
"maxTotalRAMSize": 512,
|
||||
"totalCoresUsed": -1,
|
||||
"totalInstancesUsed": 2,
|
||||
"totalRAMUsed": 256,
|
||||
"totalServerGroupsUsed": 5,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -424,28 +352,11 @@ class LimitsControllerTestV239(BaseLimitTestSuite):
|
||||
version='2.39')
|
||||
|
||||
def test_index_filtered_no_max_image_meta(self):
|
||||
absolute_limits = {
|
||||
"metadata_items": 1,
|
||||
}
|
||||
|
||||
def _get_project_quotas(context, project_id, usages=True):
|
||||
return {k: dict(limit=v, in_use=v // 2)
|
||||
for k, v in absolute_limits.items()}
|
||||
|
||||
self.mock_get_project_quotas.side_effect = _get_project_quotas
|
||||
|
||||
response = self.controller.index(self.req)
|
||||
# starting from version 2.39 there is no 'maxImageMeta' field
|
||||
# in response after removing 'image-metadata' proxy API
|
||||
expected_response = {
|
||||
"limits": {
|
||||
"rate": [],
|
||||
"absolute": {
|
||||
"maxServerMeta": 1,
|
||||
},
|
||||
},
|
||||
}
|
||||
self.assertEqual(expected_response, response)
|
||||
self.assertNotIn('maxImageMeta', response['limits']['absolute'])
|
||||
self.assertIn('maxServerMeta', response['limits']['absolute'])
|
||||
|
||||
|
||||
class LimitsControllerTestV275(BaseLimitTestSuite):
|
||||
@@ -454,23 +365,12 @@ class LimitsControllerTestV275(BaseLimitTestSuite):
|
||||
self.controller = limits_v21.LimitsController()
|
||||
|
||||
def test_index_additional_query_param_old_version(self):
|
||||
absolute_limits = {
|
||||
"metadata_items": 1,
|
||||
}
|
||||
req = fakes.HTTPRequest.blank("/?unknown=fake",
|
||||
version='2.74')
|
||||
|
||||
def _get_project_quotas(context, project_id, usages=True):
|
||||
return {k: dict(limit=v, in_use=v // 2)
|
||||
for k, v in absolute_limits.items()}
|
||||
|
||||
self.mock_get_project_quotas.side_effect = _get_project_quotas
|
||||
req = fakes.HTTPRequest.blank("/?unknown=fake", version='2.74')
|
||||
self.controller.index(req)
|
||||
self.controller.index(req)
|
||||
|
||||
def test_index_additional_query_param(self):
|
||||
req = fakes.HTTPRequest.blank("/?unknown=fake",
|
||||
version='2.75')
|
||||
req = fakes.HTTPRequest.blank("/?unknown=fake", version='2.75')
|
||||
self.assertRaises(
|
||||
exception.ValidationError,
|
||||
self.controller.index, req=req)
|
||||
|
||||
@@ -39,13 +39,18 @@ class LimitsPolicyTest(base.BasePolicyTest):
|
||||
self.req = fakes.HTTPRequest.blank('')
|
||||
|
||||
self.absolute_limits = {
|
||||
'ram': 512,
|
||||
'instances': 5,
|
||||
'cores': 21,
|
||||
'key_pairs': 10,
|
||||
'floating_ips': 10,
|
||||
'security_groups': 10,
|
||||
'injected_file_content_bytes': 1024,
|
||||
'injected_files': 20,
|
||||
'instances': 5,
|
||||
'key_pairs': 10,
|
||||
'metadata_items': 10,
|
||||
'ram': 512,
|
||||
'security_group_rules': 20,
|
||||
'security_groups': 10,
|
||||
'server_group_members': 5,
|
||||
'server_groups': 10,
|
||||
}
|
||||
|
||||
def stub_get_project_quotas(context, project_id, usages=True):
|
||||
|
||||
Reference in New Issue
Block a user