From a8a562554e8678222366fd2e766a12fee08a51b3 Mon Sep 17 00:00:00 2001 From: mounikasreeram Date: Fri, 12 Jan 2018 17:32:48 +0530 Subject: [PATCH] Enhancing Quota-show feature in kingbird. Quota show feature will display the updated quota values. This feature is enhanced by displaying the default quota values as well as updated values as in. The size of the resource column in database is increased for better usage. Change-Id: I814bd45a634342104c190f4437cae265ea3bb0f1 Closes-Bug:1740823 Closes-Bug:1742906 --- kingbird/api/controllers/v1/quota_manager.py | 19 +++++- .../migrate_repo/versions/006_sync_job.py | 2 +- kingbird/db/sqlalchemy/models.py | 2 +- .../api/v1/controllers/test_quota_manager.py | 63 +++++++++++-------- .../v1/controllers/test_quota_manager_v1.py | 37 +++-------- 5 files changed, 66 insertions(+), 57 deletions(-) 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):