diff --git a/kingbird/api/controllers/v1/quota_manager.py b/kingbird/api/controllers/v1/quota_manager.py index d260623..8cb3e2a 100644 --- a/kingbird/api/controllers/v1/quota_manager.py +++ b/kingbird/api/controllers/v1/quota_manager.py @@ -24,6 +24,7 @@ from pecan import request from kingbird.api.controllers import restcomm from kingbird.api import enforcer as enf +from kingbird.common import consts from kingbird.common import exceptions from kingbird.common.i18n import _ from kingbird.common import utils @@ -52,11 +53,26 @@ class BaseController(object): It references all other resources belonging to both the API's. """ + supported_quotas = list() def __init__(self, *args, **kwargs): super(BaseController, self).__init__(*args, **kwargs) + self.supported_quotas = list( + consts.CINDER_QUOTA_FIELDS + + consts.NEUTRON_QUOTA_FIELDS + + consts.NOVA_QUOTA_FIELDS) self.rpc_client = rpc_client.EngineClient() + def _format_quota_set(self, context, quota_set): + result = self.get_defaults(context, + CONF.kingbird_global_limit) + + for quota in self.supported_quotas: + if quota in quota_set: + result[quota] = quota_set[quota] + + return result + def get_quota(self, context, project_id, action=None): """Get quota for a specified tenant. @@ -84,7 +100,8 @@ class BaseController(object): context, project_id) else: # Get quota limits for all the resources for a project - result = db_api.quota_get_all_by_project(context, project_id) + values = db_api.quota_get_all_by_project(context, project_id) + result = self._format_quota_set(context, values) return result def get_defaults(self, context, config_defaults): diff --git a/kingbird/db/sqlalchemy/migrate_repo/versions/006_sync_job.py b/kingbird/db/sqlalchemy/migrate_repo/versions/006_sync_job.py index be47d2e..cc5250f 100644 --- a/kingbird/db/sqlalchemy/migrate_repo/versions/006_sync_job.py +++ b/kingbird/db/sqlalchemy/migrate_repo/versions/006_sync_job.py @@ -48,7 +48,7 @@ def upgrade(migrate_engine): primary_key=True), sqlalchemy.Column('target_region', sqlalchemy.String(36), primary_key=True), - sqlalchemy.Column('resource', sqlalchemy.String(36), + sqlalchemy.Column('resource', sqlalchemy.String(255), primary_key=True), sqlalchemy.Column('resource_type', sqlalchemy.String(36), nullable=False), diff --git a/kingbird/db/sqlalchemy/models.py b/kingbird/db/sqlalchemy/models.py index a20bd73..fb7332c 100644 --- a/kingbird/db/sqlalchemy/models.py +++ b/kingbird/db/sqlalchemy/models.py @@ -180,7 +180,7 @@ class ResourceSync(BASE, KingbirdBase): target_region = Column('target_region', String(36), primary_key=True) - resource = Column('resource', String(36), primary_key=True) + resource = Column('resource', String(255), primary_key=True) resource_type = Column('resource_type', String(36), nullable=False) diff --git a/kingbird/tests/unit/api/v1/controllers/test_quota_manager.py b/kingbird/tests/unit/api/v1/controllers/test_quota_manager.py index 544fa1a..7943dbb 100644 --- a/kingbird/tests/unit/api/v1/controllers/test_quota_manager.py +++ b/kingbird/tests/unit/api/v1/controllers/test_quota_manager.py @@ -21,6 +21,7 @@ from oslo_config import cfg from kingbird.api.controllers.v1 import quota_manager from kingbird.common import config from kingbird.rpc import client as rpc_client +from kingbird.tests.tempest.scenario import consts as tempest_consts from kingbird.tests.unit.api import test_root_controller as testroot from kingbird.tests import utils @@ -51,19 +52,47 @@ class TestQuotaManager(testroot.KBApiTest): @mock.patch.object(rpc_client, 'EngineClient', new=mock.Mock()) @mock.patch.object(quota_manager, 'db_api') def test_get_all_admin(self, mock_db_api): - Res = Result(TARGET_FAKE_TENANT, 'ram', 100) - mock_db_api.quota_get_all_by_project.return_value = \ - {"project_id": Res.project_id, - Res.resource: Res.hard_limit} + updated_values = {'subnet': 11} + default_values = tempest_consts.DEFAULT_QUOTAS fake_url = '/v1.0/%s/os-quota-sets/%s'\ - % (FAKE_TENANT, TARGET_FAKE_TENANT) + % (FAKE_TENANT, FAKE_TENANT) + mock_db_api.quota_get_all_by_project.return_value = updated_values + mock_db_api.quota_class_get_default.return_value = default_values response = self.app.get( fake_url, headers=ADMIN_HEADERS) - self.assertEqual(response.status_int, 200) - self.assertEqual({'quota_set': - {'project_id': TARGET_FAKE_TENANT, 'ram': 100}}, - eval(response.text)) + default_values.update(updated_values) + self.assertEqual(response.json['quota_set'], default_values) + + @mock.patch.object(rpc_client, 'EngineClient', new=mock.Mock()) + @mock.patch.object(quota_manager, 'db_api') + def test_get_tenant_with_admin(self, mock_db_api): + updated_values = {'subnet': 11} + default_values = tempest_consts.DEFAULT_QUOTAS + fake_url = '/v1.0/%s/os-quota-sets/%s'\ + % (FAKE_TENANT, TARGET_FAKE_TENANT) + mock_db_api.quota_get_all_by_project.return_value = updated_values + mock_db_api.quota_class_get_default.return_value = default_values + response = self.app.get( + fake_url, + headers=ADMIN_HEADERS) + default_values.update(updated_values) + self.assertEqual(response.json['quota_set'], default_values) + + @mock.patch.object(rpc_client, 'EngineClient', new=mock.Mock()) + @mock.patch.object(quota_manager, 'db_api') + def test_get_tenant_without_admin(self, mock_db_api): + updated_values = {'subnet': 11} + default_values = tempest_consts.DEFAULT_QUOTAS + fake_url = '/v1.0/%s/os-quota-sets/%s'\ + % (TARGET_FAKE_TENANT, TARGET_FAKE_TENANT) + mock_db_api.quota_get_all_by_project.return_value = updated_values + mock_db_api.quota_class_get_default.return_value = default_values + response = self.app.get( + fake_url, + headers=NON_ADMIN_HEADERS) + default_values.update(updated_values) + self.assertEqual(response.json['quota_set'], default_values) @mock.patch.object(rpc_client, 'EngineClient', new=mock.Mock()) @mock.patch.object(quota_manager, 'db_api') @@ -268,22 +297,6 @@ class TestQuotaManager(testroot.KBApiTest): self.app.get, fake_url, headers=NON_ADMIN_HEADERS) - @mock.patch.object(rpc_client, 'EngineClient', new=mock.Mock()) - @mock.patch.object(quota_manager, 'db_api') - def test_get_all_another_tenant_with_admin(self, mock_db_api): - fake_url = '/v1.0/%s/os-quota-sets/%s'\ - % (FAKE_TENANT, TARGET_FAKE_TENANT) - Res = Result('tenant_1', 'ram', 100) - mock_db_api.quota_get_all_by_project.return_value = \ - {"project_id": Res.project_id, - Res.resource: Res.hard_limit} - response = self.app.get( - fake_url, - headers=ADMIN_HEADERS) - self.assertEqual(response.status_int, 200) - self.assertEqual({'quota_set': {'project_id': 'tenant_1', 'ram': 100}}, - eval(response.text)) - @mock.patch.object(rpc_client, 'EngineClient', new=mock.Mock()) @mock.patch.object(quota_manager, 'db_api') def test_get_usages_another_tenant_no_admin(self, mock_db_api): diff --git a/kingbird/tests/unit/api/v1/controllers/test_quota_manager_v1.py b/kingbird/tests/unit/api/v1/controllers/test_quota_manager_v1.py index db2a23b..e446f40 100644 --- a/kingbird/tests/unit/api/v1/controllers/test_quota_manager_v1.py +++ b/kingbird/tests/unit/api/v1/controllers/test_quota_manager_v1.py @@ -21,6 +21,7 @@ from oslo_config import cfg from kingbird.api.controllers.v1 import quota_manager from kingbird.common import config from kingbird.rpc import client as rpc_client +from kingbird.tests.tempest.scenario import consts as tempest_consts from kingbird.tests.unit.api import test_root_controller as testroot from kingbird.tests import utils @@ -49,21 +50,18 @@ class TestQuotaManager(testroot.KBApiTest): @mock.patch.object(rpc_client, 'EngineClient', new=mock.Mock()) @mock.patch.object(quota_manager, 'db_api') @mock.patch.object(quota_manager, 'enf') - def test_get_quota_details_admin(self, mock_enf, mock_db_api): - Res = Result(TARGET_FAKE_TENANT, 'ram', 100) - mock_enf.enforce.return_value = True - mock_db_api.quota_get_all_by_project.return_value = \ - {"project_id": Res.project_id, - Res.resource: Res.hard_limit} + def test_get_quota_details(self, mock_enf, mock_db_api): + updated_values = {'subnet': 11} + default_values = tempest_consts.DEFAULT_QUOTAS fake_url = '/v1.1/%s/os-quota-sets/'\ % (FAKE_TENANT) + mock_db_api.quota_get_all_by_project.return_value = updated_values + mock_db_api.quota_class_get_default.return_value = default_values response = self.app.get( fake_url, headers=HEADERS) - self.assertEqual(response.status_int, 200) - self.assertEqual({'quota_set': - {'project_id': TARGET_FAKE_TENANT, 'ram': 100}}, - eval(response.text)) + default_values.update(updated_values) + self.assertEqual(response.json['quota_set'], default_values) @mock.patch.object(rpc_client, 'EngineClient', new=mock.Mock()) @mock.patch.object(quota_manager, 'db_api') @@ -259,25 +257,6 @@ class TestQuotaManager(testroot.KBApiTest): self.app.get, fake_url, headers=HEADERS) - @mock.patch.object(rpc_client, 'EngineClient', new=mock.Mock()) - @mock.patch.object(quota_manager, 'db_api') - @mock.patch.object(quota_manager, 'enf') - def test_get_complete_quota_another_tenant_with_admin(self, mock_enf, - mock_db_api): - fake_url = '/v1.1/%s/os-quota-sets'\ - % (FAKE_TENANT) - Res = Result(FAKE_TENANT, 'ram', 100) - mock_db_api.quota_get_all_by_project.return_value = \ - {"project_id": Res.project_id, - Res.resource: Res.hard_limit} - mock_enf.enforce.return_value = True - response = self.app.get( - fake_url, - headers=HEADERS) - self.assertEqual(response.status_int, 200) - self.assertEqual({'quota_set': {'project_id': FAKE_TENANT, - 'ram': 100}}, eval(response.text)) - @mock.patch.object(rpc_client, 'EngineClient', new=mock.Mock()) @mock.patch.object(quota_manager, 'enf') def test_get_usages_another_tenant_non_admin(self, mock_enf):