Resource Quota - Introduce Quota Table
Introduce Quota Table and Quota list/create API's. With this concept it will be possible to set quota on a resource within a project. Fox example X number of bay creation within a project and if the request exceeds X bay creation will not be allowed. This change only introduces the db layer changes. Change-Id: I8990052df48bdbf6eee426e88ed6c9c2f8cfd344 Partially-Implements: bp resource-quota
This commit is contained in:
parent
2a6d7c2e94
commit
faca94607a
|
@ -555,3 +555,8 @@ class TrusteeCreateFailed(MagnumException):
|
|||
|
||||
class TrusteeDeleteFailed(MagnumException):
|
||||
message = _("Failed to delete trustee %(trustee_id)")
|
||||
|
||||
|
||||
class QuotaAlreadyExists(Conflict):
|
||||
message = _("Quota for project %(project_id)s already exists "
|
||||
"for resource %(resource)s.")
|
||||
|
|
|
@ -671,3 +671,31 @@ class Connection(object):
|
|||
(asc, desc)
|
||||
:returns: A list of tuples of the specified columns.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def create_quota(self, values):
|
||||
"""Create a new Quota record for a resource in a project.
|
||||
|
||||
:param values: A dict containing several items used to identify
|
||||
and track quota for a resource in a project.
|
||||
|
||||
::
|
||||
|
||||
{
|
||||
'id': utils.generate_uuid(),
|
||||
'project_id': 'fake_project',
|
||||
'resource': 'fake_resource',
|
||||
'hard_limit': 'fake_hardlimit',
|
||||
}
|
||||
|
||||
:returns: A quota record.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def quota_get_all_by_project_id(self, project_id):
|
||||
"""Gets Quota record for all the resources in a project.
|
||||
|
||||
:param project_id: Project identifier of the project.
|
||||
|
||||
:returns: Quota record for all resources in a project.
|
||||
"""
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
# Copyright 2016 Yahoo! Inc. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
"""Introduce Quotas
|
||||
|
||||
Revision ID: ee92b41b8809
|
||||
Revises: 5d4caa6e0a42
|
||||
Create Date: 2016-02-26 18:32:08.992964
|
||||
|
||||
"""
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = 'ee92b41b8809'
|
||||
down_revision = '5d4caa6e0a42'
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
def upgrade():
|
||||
op.create_table(
|
||||
'quotas',
|
||||
sa.Column('id', sa.Integer(), nullable=False),
|
||||
sa.Column('created_at', sa.DateTime(), nullable=True),
|
||||
sa.Column('updated_at', sa.DateTime(), nullable=True),
|
||||
sa.Column('project_id', sa.String(length=255), nullable=True),
|
||||
sa.Column('resource', sa.String(length=255), nullable=True),
|
||||
sa.Column('hard_limit', sa.Integer(), nullable=False),
|
||||
sa.PrimaryKeyConstraint('id'),
|
||||
mysql_ENGINE='InnoDB',
|
||||
mysql_DEFAULT_CHARSET='UTF8'
|
||||
)
|
||||
op.create_unique_constraint(
|
||||
"uniq_quotas0project_id0resource",
|
||||
"quotas", ["project_id", "resource"])
|
|
@ -909,3 +909,19 @@ class Connection(api.Connection):
|
|||
|
||||
return _paginate_query(models.MagnumService, limit, marker,
|
||||
sort_key, sort_dir, query)
|
||||
|
||||
def create_quota(self, values):
|
||||
quotas = models.Quota()
|
||||
quotas.update(values)
|
||||
try:
|
||||
quotas.save()
|
||||
except db_exc.DBDuplicateEntry:
|
||||
raise exception.QuotaAlreadyExists(project_id=values['project_id'],
|
||||
resource=values['resource'])
|
||||
return quotas
|
||||
|
||||
def quota_get_all_by_project_id(self, project_id):
|
||||
query = model_query(models.Quota)
|
||||
result = query.filter_by(project_id=project_id).all()
|
||||
|
||||
return result
|
||||
|
|
|
@ -291,3 +291,18 @@ class MagnumService(Base):
|
|||
last_seen_up = Column(DateTime, nullable=True)
|
||||
forced_down = Column(Boolean, default=False)
|
||||
report_count = Column(Integer, nullable=False, default=0)
|
||||
|
||||
|
||||
class Quota(Base):
|
||||
"""Represents Quota for a resource within a project"""
|
||||
__tablename__ = 'quotas'
|
||||
__table_args__ = (
|
||||
schema.UniqueConstraint(
|
||||
"project_id", "resource",
|
||||
name='uniq_quotas0project_id0resource'),
|
||||
table_args()
|
||||
)
|
||||
id = Column(Integer, primary_key=True)
|
||||
project_id = Column(String(255))
|
||||
resource = Column(String(255))
|
||||
hard_limit = Column(Integer())
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
# Copyright 2016 Yahoo! Inc.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
"""Tests for manipulating Quota via the DB API"""
|
||||
|
||||
from magnum.common import exception
|
||||
from magnum.tests.unit.db import base
|
||||
from magnum.tests.unit.db import utils
|
||||
|
||||
|
||||
class DbQuotaTestCase(base.DbTestCase):
|
||||
|
||||
def test_create_quota(self):
|
||||
utils.create_test_quotas()
|
||||
|
||||
def test_create_quota_already_exists(self):
|
||||
utils.create_test_quotas()
|
||||
self.assertRaises(exception.QuotaAlreadyExists,
|
||||
utils.create_test_quotas)
|
||||
|
||||
def test_get_quota_all(self):
|
||||
q = utils.create_test_quotas()
|
||||
res = self.dbapi.quota_get_all_by_project_id(
|
||||
project_id='fake_project')
|
||||
for r in res:
|
||||
self.assertEqual(q.id, r.id)
|
||||
self.assertEqual(q.hard_limit, r.hard_limit)
|
||||
self.assertEqual(q.project_id, r.project_id)
|
||||
self.assertEqual(q.resource, r.resource)
|
|
@ -308,3 +308,28 @@ def create_test_magnum_service(**kw):
|
|||
del magnum_service['id']
|
||||
dbapi = db_api.get_instance()
|
||||
return dbapi.create_magnum_service(magnum_service)
|
||||
|
||||
|
||||
def get_test_quotas(**kw):
|
||||
return {
|
||||
'id': kw.get('', 18),
|
||||
'project_id': kw.get('project_id', 'fake_project'),
|
||||
'resource': kw.get('resource', 'fake_resource'),
|
||||
'hard_limit': kw.get('hard_limit', 10),
|
||||
'created_at': kw.get('created_at'),
|
||||
'updated_at': kw.get('updated_at'),
|
||||
}
|
||||
|
||||
|
||||
def create_test_quotas(**kw):
|
||||
"""Create test quotas entry in DB and return quotas DB object.
|
||||
|
||||
:param kw: kwargs with overriding values for quota attributes.
|
||||
:returns: Test quotas DB object.
|
||||
"""
|
||||
quotas = get_test_quotas(**kw)
|
||||
# Let DB generate ID if it isn't specified explicitly
|
||||
if 'id' not in kw:
|
||||
del quotas['id']
|
||||
dbapi = db_api.get_instance()
|
||||
return dbapi.create_quota(quotas)
|
||||
|
|
Loading…
Reference in New Issue