From 0aabb8a6febca8d98a750d1bdc78f3160b9684fe Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Thu, 9 Sep 2010 13:40:18 -0700 Subject: mocking out quotas --- nova/db/sqlalchemy/models.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'nova/db') diff --git a/nova/db/sqlalchemy/models.py b/nova/db/sqlalchemy/models.py index 679a44d21..2fcade7de 100644 --- a/nova/db/sqlalchemy/models.py +++ b/nova/db/sqlalchemy/models.py @@ -266,6 +266,20 @@ class Volume(BASE, NovaBase): attach_status = Column(String(255)) # TODO(vish): enum +class Quota(BASE, NovaBase): + """Represents quota overrides for a project""" + __tablename__ = 'quotas' + id = Column(Integer, primary_key=True) + + project_id = Column(String(255)) + + instances = Column(Integer) + cores = Column(Integer) + volumes = Column(Integer) + gigabytes = Column(Integer) + floating_ips = Column(Integer) + + class ExportDevice(BASE, NovaBase): """Represates a shelf and blade that a volume can be exported on""" __tablename__ = 'export_devices' -- cgit From c577e91ee3a3eb87a393da2449cab95069a785f4 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Thu, 9 Sep 2010 20:10:31 -0700 Subject: database support for quotas --- nova/db/api.py | 27 +++++++++++++++++++++++++++ nova/db/sqlalchemy/api.py | 43 ++++++++++++++++++++++++++++++++++++++++++- nova/db/sqlalchemy/models.py | 21 +++++++++++++++++++++ 3 files changed, 90 insertions(+), 1 deletion(-) (limited to 'nova/db') diff --git a/nova/db/api.py b/nova/db/api.py index d81673fad..c22c84768 100644 --- a/nova/db/api.py +++ b/nova/db/api.py @@ -195,6 +195,10 @@ def instance_create(context, values): return IMPL.instance_create(context, values) +def instance_data_get_for_project(context, project_id): + """Get (instance_count, core_count) for project.""" + return IMPL.instance_data_get_for_project(context, project_id) + def instance_destroy(context, instance_id): """Destroy the instance or raise if it does not exist.""" return IMPL.instance_destroy(context, instance_id) @@ -379,6 +383,29 @@ def export_device_create(context, values): ################### +def quota_create(context, values): + """Create a quota from the values dictionary.""" + return IMPL.quota_create(context, values) + + +def quota_get(context, project_id): + """Retrieve a quota or raise if it does not exist.""" + return IMPL.quota_get(context, project_id) + + +def quota_update(context, project_id, values): + """Update a quota from the values dictionary.""" + return IMPL.quota_update(context, project_id, values) + + +def quota_destroy(context, project_id): + """Destroy the quota or raise if it does not exist.""" + return IMPL.quota_destroy(context, project_id) + + +################### + + def volume_allocate_shelf_and_blade(context, volume_id): """Atomically allocate a free shelf and blade from the pool.""" return IMPL.volume_allocate_shelf_and_blade(context, volume_id) diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index 4ea7a9071..4b01725ce 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -26,6 +26,7 @@ from nova.db.sqlalchemy import models from nova.db.sqlalchemy.session import get_session from sqlalchemy import or_ from sqlalchemy.orm import joinedload_all +from sqlalchemy.sql import func FLAGS = flags.FLAGS @@ -264,6 +265,15 @@ def instance_create(_context, values): return instance_ref.id +def instance_data_get_for_project(_context, project_id): + session = get_session() + return session.query(func.count(models.Instance.id), + func.sum(models.Instance.vcpus) + ).filter_by(project_id=project_id + ).filter_by(deleted=False + ).first() + + def instance_destroy(_context, instance_id): session = get_session() with session.begin(): @@ -534,6 +544,37 @@ def export_device_create(_context, values): ################### +def quota_create(_context, values): + quota_ref = models.Quota() + for (key, value) in values.iteritems(): + quota_ref[key] = value + quota_ref.save() + return quota_ref + + +def quota_get(_context, project_id): + return models.Quota.find_by_str(project_id) + + +def quota_update(_context, project_id, values): + session = get_session() + with session.begin(): + quota_ref = models.Quota.find_by_str(project_id, session=session) + for (key, value) in values.iteritems(): + quota_ref[key] = value + quota_ref.save(session=session) + + +def quota_destroy(_context, project_id): + session = get_session() + with session.begin(): + quota_ref = models.Quota.find_by_str(project_id, session=session) + quota_ref.delete(session=session) + + +################### + + def volume_allocate_shelf_and_blade(_context, volume_id): session = get_session() with session.begin(): @@ -621,7 +662,7 @@ def volume_get_instance(_context, volume_id): def volume_get_shelf_and_blade(_context, volume_id): session = get_session() - export_device = session.query(models.ExportDevice + export_device = session.query(models.exportdevice ).filter_by(volume_id=volume_id ).first() if not export_device: diff --git a/nova/db/sqlalchemy/models.py b/nova/db/sqlalchemy/models.py index 2fcade7de..7f510301a 100644 --- a/nova/db/sqlalchemy/models.py +++ b/nova/db/sqlalchemy/models.py @@ -222,6 +222,11 @@ class Instance(BASE, NovaBase): state = Column(Integer) state_description = Column(String(255)) + memory_mb = Column(Integer) + vcpus = Column(Integer) + local_gb = Column(Integer) + + hostname = Column(String(255)) host = Column(String(255)) # , ForeignKey('hosts.id')) @@ -279,6 +284,22 @@ class Quota(BASE, NovaBase): gigabytes = Column(Integer) floating_ips = Column(Integer) + @property + def str_id(self): + return self.project_id + + @classmethod + def find_by_str(cls, str_id, session=None, deleted=False): + if not session: + session = get_session() + try: + return session.query(cls + ).filter_by(project_id=str_id + ).filter_by(deleted=deleted + ).one() + except exc.NoResultFound: + new_exc = exception.NotFound("No model for project_id %s" % str_id) + raise new_exc.__class__, new_exc, sys.exc_info()[2] class ExportDevice(BASE, NovaBase): """Represates a shelf and blade that a volume can be exported on""" -- cgit From 8e4f102819a1424a25f89ed34040b1298ed9563a Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Sat, 11 Sep 2010 18:45:15 -0700 Subject: use gigabytes and cores --- nova/db/sqlalchemy/api.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'nova/db') diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index 735e88145..8ca0f790b 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -85,9 +85,9 @@ def service_get_all_compute_sorted(context): # FROM instances GROUP BY host) AS inst_count # ON services.host = inst_count.host topic = 'compute' - label = 'instance_count' + label = 'instance_cores' subq = session.query(models.Instance.host, - func.count('*').label(label) + func.sum('cores').label(label) ).filter_by(deleted=False ).group_by(models.Instance.host ).subquery() @@ -119,9 +119,9 @@ def service_get_all_volume_sorted(context): session = get_session() with session.begin(): topic = 'volume' - label = 'volume_count' + label = 'volume_gigabytes' subq = session.query(models.Volume.host, - func.count('*').label(label) + func.count('size').label(label) ).filter_by(deleted=False ).group_by(models.Volume.host ).subquery() -- cgit From 68ff059c7a6287825871f96cde8039f04aec1f37 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Sat, 11 Sep 2010 18:57:15 -0700 Subject: update query and test --- nova/db/sqlalchemy/api.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'nova/db') diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index 574a6f460..75131e093 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -79,15 +79,15 @@ def service_get_all_compute_sorted(context): session = get_session() with session.begin(): # NOTE(vish): The intended query is below - # SELECT services.*, inst_count.instance_count + # SELECT services.*, inst_cores.instance_cores # FROM services LEFT OUTER JOIN - # (SELECT host, count(*) AS instance_count - # FROM instances GROUP BY host) AS inst_count - # ON services.host = inst_count.host + # (SELECT host, sum(instances.vcpus) AS instance_cores + # FROM instances GROUP BY host) AS inst_cores + # ON services.host = inst_cores.host topic = 'compute' label = 'instance_cores' subq = session.query(models.Instance.host, - func.sum('cores').label(label) + func.sum(models.Instance.vcpus).label(label) ).filter_by(deleted=False ).group_by(models.Instance.host ).subquery() @@ -121,7 +121,7 @@ def service_get_all_volume_sorted(context): topic = 'volume' label = 'volume_gigabytes' subq = session.query(models.Volume.host, - func.count('size').label(label) + func.sum(models.Volume.size).label(label) ).filter_by(deleted=False ).group_by(models.Volume.host ).subquery() -- cgit From d05fe5d18ba3a62a1792634e7ba3c2f11d7b89bd Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Sat, 11 Sep 2010 19:40:38 -0700 Subject: tests for volumes work --- nova/db/sqlalchemy/api.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'nova/db') diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index 75131e093..d612fe669 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -67,7 +67,7 @@ def service_get_all_by_topic(context, topic): def _service_get_all_topic_subquery(_context, session, topic, subq, label): sort_value = getattr(subq.c, label) - return session.query(models.Service, sort_value + return session.query(models.Service, func.coalesce(sort_value, 0) ).filter_by(topic=topic ).filter_by(deleted=False ).outerjoin((subq, models.Service.host == subq.c.host) @@ -79,9 +79,10 @@ def service_get_all_compute_sorted(context): session = get_session() with session.begin(): # NOTE(vish): The intended query is below - # SELECT services.*, inst_cores.instance_cores + # SELECT services.*, COALESCE(inst_cores.instance_cores, + # 0) # FROM services LEFT OUTER JOIN - # (SELECT host, sum(instances.vcpus) AS instance_cores + # (SELECT host, SUM(instances.vcpus) AS instance_cores # FROM instances GROUP BY host) AS inst_cores # ON services.host = inst_cores.host topic = 'compute' @@ -104,7 +105,7 @@ def service_get_all_network_sorted(context): topic = 'network' label = 'network_count' subq = session.query(models.Network.host, - func.count('*').label(label) + func.count(models.Network.id).label(label) ).filter_by(deleted=False ).group_by(models.Network.host ).subquery() -- cgit