summaryrefslogtreecommitdiffstats
path: root/nova/db
diff options
context:
space:
mode:
authorVishvananda Ishaya <vishvananda@yahoo.com>2010-09-30 18:33:23 -0700
committerVishvananda Ishaya <vishvananda@yahoo.com>2010-09-30 18:33:23 -0700
commite0da95213631b3dc383ce69d6dff044c5841f143 (patch)
treea3429d496c2b310eb08fbe445cde83f2c0b9d767 /nova/db
parente16031ddd09d668972c38372a28ec7f898f571f6 (diff)
parentc9cb22f87561fad4ba57865d8a614ca024393f13 (diff)
merged trunk, removed extra quotas
Diffstat (limited to 'nova/db')
-rw-r--r--nova/db/api.py72
-rw-r--r--nova/db/sqlalchemy/api.py149
-rw-r--r--nova/db/sqlalchemy/models.py29
3 files changed, 156 insertions, 94 deletions
diff --git a/nova/db/api.py b/nova/db/api.py
index 848ec2682..a39d5665e 100644
--- a/nova/db/api.py
+++ b/nova/db/api.py
@@ -161,10 +161,15 @@ def floating_ip_get_all(context):
def floating_ip_get_all_by_host(context, host):
- """Get all floating ips."""
+ """Get all floating ips by host."""
return IMPL.floating_ip_get_all_by_host(context, host)
+def floating_ip_get_all_by_project(context, project_id):
+ """Get all floating ips by project."""
+ return IMPL.floating_ip_get_all_by_project(context, project_id)
+
+
def floating_ip_get_by_address(context, address):
"""Get a floating ip by address or raise if it doesn't exist."""
return IMPL.floating_ip_get_by_address(context, address)
@@ -204,6 +209,11 @@ def fixed_ip_disassociate(context, address):
return IMPL.fixed_ip_disassociate(context, address)
+def fixed_ip_disassociate_all_by_timeout(context, host, time):
+ """Disassociate old fixed ips from host"""
+ return IMPL.fixed_ip_disassociate_all_by_timeout(context, host, time)
+
+
def fixed_ip_get_by_address(context, address):
"""Get a fixed ip by address or raise if it does not exist."""
return IMPL.fixed_ip_get_by_address(context, address)
@@ -251,15 +261,18 @@ def instance_get_all(context):
"""Get all instances."""
return IMPL.instance_get_all(context)
+def instance_get_all_by_user(context, user_id):
+ """Get all instances."""
+ return IMPL.instance_get_all(context, user_id)
-def instance_get_by_project(context, project_id):
+def instance_get_all_by_project(context, project_id):
"""Get all instance belonging to a project."""
- return IMPL.instance_get_by_project(context, project_id)
+ return IMPL.instance_get_all_by_project(context, project_id)
-def instance_get_by_reservation(context, reservation_id):
+def instance_get_all_by_reservation(context, reservation_id):
"""Get all instance belonging to a reservation."""
- return IMPL.instance_get_by_reservation(context, reservation_id)
+ return IMPL.instance_get_all_by_reservation(context, reservation_id)
def instance_get_fixed_address(context, instance_id):
@@ -272,9 +285,9 @@ def instance_get_floating_address(context, instance_id):
return IMPL.instance_get_floating_address(context, instance_id)
-def instance_get_by_str(context, str_id):
- """Get an instance by string id."""
- return IMPL.instance_get_by_str(context, str_id)
+def instance_get_by_ec2_id(context, ec2_id):
+ """Get an instance by ec2 id."""
+ return IMPL.instance_get_by_ec2_id(context, ec2_id)
def instance_is_vpn(context, instance_id):
@@ -393,9 +406,12 @@ def network_index_count(context):
return IMPL.network_index_count(context)
-def network_index_create(context, values):
- """Create a network index from the values dict"""
- return IMPL.network_index_create(context, values)
+def network_index_create_safe(context, values):
+ """Create a network index from the values dict
+
+ The index is not returned. If the create violates the unique
+ constraints because the index already exists, no exception is raised."""
+ return IMPL.network_index_create_safe(context, values)
def network_set_cidr(context, network_id, cidr):
@@ -475,6 +491,7 @@ def quota_destroy(context, project_id):
###################
+
def auth_destroy_token(context, token):
"""Destroy an auth token"""
return IMPL.auth_destroy_token(context, token)
@@ -491,29 +508,6 @@ def auth_create_token(context, token):
###################
-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)
@@ -559,14 +553,14 @@ def volume_get_instance(context, volume_id):
return IMPL.volume_get_instance(context, volume_id)
-def volume_get_by_project(context, project_id):
+def volume_get_all_by_project(context, project_id):
"""Get all volumes belonging to a project."""
- return IMPL.volume_get_by_project(context, project_id)
+ return IMPL.volume_get_all_by_project(context, project_id)
-def volume_get_by_str(context, str_id):
- """Get a volume by string id."""
- return IMPL.volume_get_by_str(context, str_id)
+def volume_get_by_ec2_id(context, ec2_id):
+ """Get a volume by ec2 id."""
+ return IMPL.volume_get_by_ec2_id(context, ec2_id)
def volume_get_shelf_and_blade(context, volume_id):
diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py
index e1dad129c..568d7ea61 100644
--- a/nova/db/sqlalchemy/api.py
+++ b/nova/db/sqlalchemy/api.py
@@ -22,12 +22,13 @@ Implementation of SQLAlchemy backend
from nova import db
from nova import exception
from nova import flags
+from nova import utils
from nova.db.sqlalchemy import models
from nova.db.sqlalchemy.session import get_session
from sqlalchemy import or_
from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm import joinedload_all
-from sqlalchemy.sql import func
+from sqlalchemy.sql import exists, func
FLAGS = flags.FLAGS
@@ -62,6 +63,7 @@ def service_get_all_by_topic(context, topic):
session = get_session()
return session.query(models.Service
).filter_by(deleted=False
+ ).filter_by(disabled=False
).filter_by(topic=topic
).all()
@@ -71,6 +73,7 @@ def _service_get_all_topic_subquery(_context, session, topic, subq, label):
return session.query(models.Service, func.coalesce(sort_value, 0)
).filter_by(topic=topic
).filter_by(deleted=False
+ ).filter_by(disabled=False
).outerjoin((subq, models.Service.host == subq.c.host)
).order_by(sort_value
).all()
@@ -164,6 +167,7 @@ def floating_ip_allocate_address(_context, host, project_id):
floating_ip_ref = session.query(models.FloatingIp
).filter_by(host=host
).filter_by(fixed_ip_id=None
+ ).filter_by(project_id=None
).filter_by(deleted=False
).with_lockmode('update'
).first()
@@ -251,6 +255,14 @@ def floating_ip_get_all_by_host(_context, host):
).filter_by(deleted=False
).all()
+def floating_ip_get_all_by_project(_context, project_id):
+ session = get_session()
+ return session.query(models.FloatingIp
+ ).options(joinedload_all('fixed_ip.instance')
+ ).filter_by(project_id=project_id
+ ).filter_by(deleted=False
+ ).all()
+
def floating_ip_get_by_address(_context, address):
return models.FloatingIp.find_by_str(address)
@@ -325,8 +337,32 @@ def fixed_ip_disassociate(_context, address):
fixed_ip_ref.save(session=session)
+def fixed_ip_disassociate_all_by_timeout(_context, host, time):
+ session = get_session()
+ # NOTE(vish): The nested select is because sqlite doesn't support
+ # JOINs in UPDATEs.
+ result = session.execute('UPDATE fixed_ips SET instance_id = NULL, '
+ 'leased = 0 '
+ 'WHERE network_id IN (SELECT id FROM networks '
+ 'WHERE host = :host) '
+ 'AND updated_at < :time '
+ 'AND instance_id IS NOT NULL '
+ 'AND allocated = 0',
+ {'host': host,
+ 'time': time.isoformat()})
+ return result.rowcount
+
+
def fixed_ip_get_by_address(_context, address):
- return models.FixedIp.find_by_str(address)
+ session = get_session()
+ result = session.query(models.FixedIp
+ ).options(joinedload_all('instance')
+ ).filter_by(address=address
+ ).filter_by(deleted=False
+ ).first()
+ if not result:
+ raise exception.NotFound("No model for address %s" % address)
+ return result
def fixed_ip_get_instance(_context, address):
@@ -357,9 +393,15 @@ def instance_create(_context, values):
instance_ref = models.Instance()
for (key, value) in values.iteritems():
instance_ref[key] = value
- instance_ref.save()
- return instance_ref
+ session = get_session()
+ with session.begin():
+ while instance_ref.ec2_id == None:
+ ec2_id = utils.generate_uid(instance_ref.__prefix__)
+ if not instance_ec2_id_exists(_context, ec2_id, session=session):
+ instance_ref.ec2_id = ec2_id
+ instance_ref.save(session=session)
+ return instance_ref
def instance_data_get_for_project(_context, project_id):
session = get_session()
@@ -390,8 +432,15 @@ def instance_get_all(context):
).filter_by(deleted=_deleted(context)
).all()
+def instance_get_all_by_user(context, user_id):
+ session = get_session()
+ return session.query(models.Instance
+ ).options(joinedload_all('fixed_ip.floating_ips')
+ ).filter_by(deleted=_deleted(context)
+ ).filter_by(user_id=user_id
+ ).all()
-def instance_get_by_project(context, project_id):
+def instance_get_all_by_project(context, project_id):
session = get_session()
return session.query(models.Instance
).options(joinedload_all('fixed_ip.floating_ips')
@@ -400,7 +449,7 @@ def instance_get_by_project(context, project_id):
).all()
-def instance_get_by_reservation(_context, reservation_id):
+def instance_get_all_by_reservation(_context, reservation_id):
session = get_session()
return session.query(models.Instance
).options(joinedload_all('fixed_ip.floating_ips')
@@ -409,8 +458,22 @@ def instance_get_by_reservation(_context, reservation_id):
).all()
-def instance_get_by_str(context, str_id):
- return models.Instance.find_by_str(str_id, deleted=_deleted(context))
+def instance_get_by_ec2_id(context, ec2_id):
+ session = get_session()
+ instance_ref = session.query(models.Instance
+ ).filter_by(ec2_id=ec2_id
+ ).filter_by(deleted=_deleted(context)
+ ).first()
+ if not instance_ref:
+ raise exception.NotFound('Instance %s not found' % (ec2_id))
+
+ return instance_ref
+
+
+def instance_ec2_id_exists(context, ec2_id, session=None):
+ if not session:
+ session = get_session()
+ return session.query(exists().where(models.Instance.id==ec2_id)).one()[0]
def instance_get_fixed_address(_context, instance_id):
@@ -571,6 +634,7 @@ def network_get(_context, network_id):
def network_get_associated_fixed_ips(_context, network_id):
session = get_session()
return session.query(models.FixedIp
+ ).options(joinedload_all('instance')
).filter_by(network_id=network_id
).filter(models.FixedIp.instance_id != None
).filter_by(deleted=False
@@ -608,11 +672,14 @@ def network_index_count(_context):
return models.NetworkIndex.count()
-def network_index_create(_context, values):
+def network_index_create_safe(_context, values):
network_index_ref = models.NetworkIndex()
for (key, value) in values.iteritems():
network_index_ref[key] = value
- network_index_ref.save()
+ try:
+ network_index_ref.save()
+ except IntegrityError:
+ pass
def network_set_host(_context, network_id, host_id):
@@ -685,37 +752,6 @@ def export_device_create_safe(_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 auth_destroy_token(_context, token):
session = get_session()
session.delete(token)
@@ -734,7 +770,7 @@ def auth_create_token(_context, token):
tk[k] = v
tk.save()
return tk
-
+
###################
@@ -803,7 +839,14 @@ def volume_create(_context, values):
volume_ref = models.Volume()
for (key, value) in values.iteritems():
volume_ref[key] = value
- volume_ref.save()
+
+ session = get_session()
+ with session.begin():
+ while volume_ref.ec2_id == None:
+ ec2_id = utils.generate_uid(volume_ref.__prefix__)
+ if not volume_ec2_id_exists(_context, ec2_id, session=session):
+ volume_ref.ec2_id = ec2_id
+ volume_ref.save(session=session)
return volume_ref
@@ -848,7 +891,7 @@ def volume_get_all(context):
return models.Volume.all(deleted=_deleted(context))
-def volume_get_by_project(context, project_id):
+def volume_get_all_by_project(context, project_id):
session = get_session()
return session.query(models.Volume
).filter_by(project_id=project_id
@@ -856,8 +899,22 @@ def volume_get_by_project(context, project_id):
).all()
-def volume_get_by_str(context, str_id):
- return models.Volume.find_by_str(str_id, deleted=_deleted(context))
+def volume_get_by_ec2_id(context, ec2_id):
+ session = get_session()
+ volume_ref = session.query(models.Volume
+ ).filter_by(ec2_id=ec2_id
+ ).filter_by(deleted=_deleted(context)
+ ).first()
+ if not volume_ref:
+ raise exception.NotFound('Volume %s not found' % (ec2_id))
+
+ return volume_ref
+
+
+def volume_ec2_id_exists(context, ec2_id, session=None):
+ if not session:
+ session = get_session()
+ return session.query(exists().where(models.Volume.id==ec2_id)).one()[0]
def volume_get_instance(_context, volume_id):
diff --git a/nova/db/sqlalchemy/models.py b/nova/db/sqlalchemy/models.py
index a03a1d2d5..5ef6c3271 100644
--- a/nova/db/sqlalchemy/models.py
+++ b/nova/db/sqlalchemy/models.py
@@ -126,6 +126,7 @@ class NovaBase(object):
# __tablename__ = 'images'
# __prefix__ = 'ami'
# id = Column(Integer, primary_key=True)
+# ec2_id = Column(String(12), unique=True)
# user_id = Column(String(255))
# project_id = Column(String(255))
# image_type = Column(String(255))
@@ -173,6 +174,7 @@ class Service(BASE, NovaBase):
binary = Column(String(255))
topic = Column(String(255))
report_count = Column(Integer, nullable=False, default=0)
+ disabled = Column(Boolean, default=False)
@classmethod
def find_by_args(cls, host, binary, session=None, deleted=False):
@@ -195,6 +197,9 @@ class Instance(BASE, NovaBase):
__tablename__ = 'instances'
__prefix__ = 'i'
id = Column(Integer, primary_key=True)
+ ec2_id = Column(String(10), unique=True)
+
+ admin_pass = Column(String(255))
user_id = Column(String(255))
project_id = Column(String(255))
@@ -209,12 +214,14 @@ class Instance(BASE, NovaBase):
@property
def name(self):
- return self.str_id
+ return self.ec2_id
image_id = Column(String(255))
kernel_id = Column(String(255))
ramdisk_id = Column(String(255))
+ server_name = Column(String(255))
+
# image_id = Column(Integer, ForeignKey('images.id'), nullable=True)
# kernel_id = Column(Integer, ForeignKey('images.id'), nullable=True)
# ramdisk_id = Column(Integer, ForeignKey('images.id'), nullable=True)
@@ -234,7 +241,6 @@ class Instance(BASE, NovaBase):
vcpus = Column(Integer)
local_gb = Column(Integer)
-
hostname = Column(String(255))
host = Column(String(255)) # , ForeignKey('hosts.id'))
@@ -248,6 +254,10 @@ class Instance(BASE, NovaBase):
scheduled_at = Column(DateTime)
launched_at = Column(DateTime)
terminated_at = Column(DateTime)
+
+ display_name = Column(String(255))
+ display_description = Column(String(255))
+
# TODO(vish): see Ewan's email about state improvements, probably
# should be in a driver base class or some such
# vmstate_state = running, halted, suspended, paused
@@ -265,6 +275,7 @@ class Volume(BASE, NovaBase):
__tablename__ = 'volumes'
__prefix__ = 'vol'
id = Column(Integer, primary_key=True)
+ ec2_id = Column(String(12), unique=True)
user_id = Column(String(255))
project_id = Column(String(255))
@@ -283,6 +294,10 @@ class Volume(BASE, NovaBase):
launched_at = Column(DateTime)
terminated_at = Column(DateTime)
+ display_name = Column(String(255))
+ display_description = Column(String(255))
+
+
class Quota(BASE, NovaBase):
"""Represents quota overrides for a project"""
__tablename__ = 'quotas'
@@ -393,14 +408,14 @@ class NetworkIndex(BASE, NovaBase):
"""
__tablename__ = 'network_indexes'
id = Column(Integer, primary_key=True)
- index = Column(Integer)
+ index = Column(Integer, unique=True)
network_id = Column(Integer, ForeignKey('networks.id'), nullable=True)
network = relationship(Network, backref=backref('network_index',
uselist=False))
class AuthToken(BASE, NovaBase):
- """Represents an authorization token for all API transactions. Fields
- are a string representing the actual token and a user id for mapping
+ """Represents an authorization token for all API transactions. Fields
+ are a string representing the actual token and a user id for mapping
to the actual user"""
__tablename__ = 'auth_tokens'
token_hash = Column(String(255), primary_key=True)
@@ -455,10 +470,6 @@ class FloatingIp(BASE, NovaBase):
project_id = Column(String(255))
host = Column(String(255)) # , ForeignKey('hosts.id'))
- @property
- def str_id(self):
- return self.address
-
@classmethod
def find_by_str(cls, str_id, session=None, deleted=False):
if not session: