summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDevin Carlen <devin.carlen@gmail.com>2010-09-29 13:26:14 -0700
committerDevin Carlen <devin.carlen@gmail.com>2010-09-29 13:26:14 -0700
commite258998923b7e8fa92656aa409f875b640df930c (patch)
tree4d01a99008e781b76642ce87f3703996f6586fd8
parentfe139bbdee60aadd720cb7a83d0846f2824c078f (diff)
downloadnova-e258998923b7e8fa92656aa409f875b640df930c.tar.gz
nova-e258998923b7e8fa92656aa409f875b640df930c.tar.xz
nova-e258998923b7e8fa92656aa409f875b640df930c.zip
Progress on volumes
Fixed foreign keys to respect deleted flag
-rw-r--r--nova/db/sqlalchemy/api.py130
-rw-r--r--nova/db/sqlalchemy/models.py35
2 files changed, 118 insertions, 47 deletions
diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py
index b5847d299..28b937233 100644
--- a/nova/db/sqlalchemy/api.py
+++ b/nova/db/sqlalchemy/api.py
@@ -30,7 +30,7 @@ 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.orm import joinedload, joinedload_all
from sqlalchemy.sql import exists, func
FLAGS = flags.FLAGS
@@ -811,6 +811,7 @@ def quota_destroy(_context, project_id):
def volume_allocate_shelf_and_blade(_context, volume_id):
+ # TODO(devcamcar): Make admin only
session = get_session()
with session.begin():
export_device = session.query(models.ExportDevice
@@ -839,7 +840,7 @@ def volume_attached(_context, volume_id, instance_id, mountpoint):
volume_ref.save(session=session)
-def volume_create(_context, values):
+def volume_create(context, values):
volume_ref = models.Volume()
for (key, value) in values.iteritems():
volume_ref[key] = value
@@ -848,7 +849,7 @@ def volume_create(_context, values):
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):
+ 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
@@ -876,10 +877,10 @@ def volume_destroy(_context, volume_id):
{'id': volume_id})
-def volume_detached(_context, volume_id):
+def volume_detached(context, volume_id):
session = get_session()
with session.begin():
- volume_ref = models.Volume.find(volume_id, session=session)
+ volume_ref = volume_get(context, volume_id, session=session)
volume_ref['status'] = 'available'
volume_ref['mountpoint'] = None
volume_ref['attach_status'] = 'detached'
@@ -887,27 +888,29 @@ def volume_detached(_context, volume_id):
volume_ref.save(session=session)
-def volume_get(context, volume_id):
- session = get_session()
+def volume_get(context, volume_id, session=None):
+ if not session:
+ session = get_session()
+ result = None
if is_admin_context(context):
- volume_ref = session.query(models.Volume
- ).filter_by(id=volume_id
- ).filter_by(deleted=_deleted(context)
- ).first()
- if not volume_ref:
- raise exception.NotFound('No volume for id %s' % volume_id)
+ result = session.query(models.Volume
+ ).filter_by(id=volume_id
+ ).filter_by(deleted=_deleted(context)
+ ).first()
+ elif is_user_context(context):
+ result = session.query(models.Volume
+ ).filter_by(project_id=context.project.project_id
+ ).filter_by(id=volume_id
+ ).filter_by(deleted=False
+ ).first()
+ else:
+ raise exception.NotAuthorized()
- if is_user_context(context):
- volume_ref = session.query(models.Volume
- ).filter_by(project_id=project_id
- ).filter_by(id=volume_id
- ).filter_by(deleted=False
- ).first()
- if not volume_ref:
- raise exception.NotFound('No volume for id %s' % volume_id)
+ if not result:
+ raise exception.NotFound('No volume for id %s' % volume_id)
- raise exception.NotAuthorized()
+ return result
def volume_get_all(context):
@@ -916,6 +919,7 @@ def volume_get_all(context):
raise exception.NotAuthorized()
+
def volume_get_all_by_project(context, project_id):
if is_user_context(context):
if context.project.id != project_id:
@@ -932,42 +936,92 @@ def volume_get_all_by_project(context, project_id):
def volume_get_by_ec2_id(context, ec2_id):
session = get_session()
- volume_ref = session.query(models.Volume
+ result = None
+
+ if is_admin_context(context):
+ result = 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))
+ elif is_user_context(context):
+ result = session.query(models.Volume
+ ).filter_by(project_id=context.project.id
+ ).filter_by(ec2_id=ec2_id
+ ).filter_by(deleted=False
+ ).first()
+ else:
+ raise exception.NotAuthorized()
- return volume_ref
+ if not result:
+ raise exception.NotFound('Volume %s not found' % ec2_id)
+
+ return result
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]
+
+ if is_admin_context(context) or is_user_context(context):
+ return session.query(exists(
+ ).where(models.Volume.id==ec2_id)
+ ).one()[0]
+ else:
+ raise exception.NotAuthorized()
-def volume_get_instance(_context, volume_id):
+def volume_get_instance(context, volume_id):
session = get_session()
- with session.begin():
- return models.Volume.find(volume_id, session=session).instance
+ result = None
+
+ if is_admin_context(context):
+ result = session.query(models.Volume
+ ).filter_by(id=volume_id
+ ).filter_by(deleted=_deleted(context)
+ ).options(joinedload('instance')
+ ).first()
+ elif is_user_context(context):
+ result = session.query(models.Volume
+ ).filter_by(project_id=context.project.id
+ ).filter_by(deleted=False
+ ).options(joinedload('instance')
+ ).first()
+ else:
+ raise exception.NotAuthorized()
+
+ if not result:
+ raise exception.NotFound('Volume %s not found' % ec2_id)
+
+ return result.instance
-def volume_get_shelf_and_blade(_context, volume_id):
+def volume_get_shelf_and_blade(context, volume_id):
session = get_session()
- export_device = session.query(models.ExportDevice
- ).filter_by(volume_id=volume_id
- ).first()
- if not export_device:
+ result = None
+
+ if is_admin_context(context):
+ result = session.query(models.ExportDevice
+ ).filter_by(volume_id=volume_id
+ ).first()
+ elif is_user_context(context):
+ result = session.query(models.ExportDevice
+ ).join(models.Volume
+ ).filter(models.Volume.project_id==context.project.id
+ ).filter_by(volume_id=volume_id
+ ).first()
+ else:
+ raise exception.NotAuthorized()
+
+ if not result:
raise exception.NotFound()
- return (export_device.shelf_id, export_device.blade_id)
+ return (result.shelf_id, result.blade_id)
-def volume_update(_context, volume_id, values):
+
+def volume_update(context, volume_id, values):
session = get_session()
with session.begin():
- volume_ref = models.Volume.find(volume_id, session=session)
+ volume_ref = volume_get(context, volume_id, session=session)
for (key, value) in values.iteritems():
volume_ref[key] = value
volume_ref.save(session=session)
diff --git a/nova/db/sqlalchemy/models.py b/nova/db/sqlalchemy/models.py
index 01e58b05e..1b9edf475 100644
--- a/nova/db/sqlalchemy/models.py
+++ b/nova/db/sqlalchemy/models.py
@@ -282,7 +282,11 @@ class Volume(BASE, NovaBase):
size = Column(Integer)
availability_zone = Column(String(255)) # TODO(vish): foreign key?
instance_id = Column(Integer, ForeignKey('instances.id'), nullable=True)
- instance = relationship(Instance, backref=backref('volumes'))
+ instance = relationship(Instance,
+ backref=backref('volumes'),
+ foreign_keys=instance_id,
+ primaryjoin='and_(Volume.instance_id==Instance.id,'
+ 'Volume.deleted==False)')
mountpoint = Column(String(255))
attach_time = Column(String(255)) # TODO(vish): datetime
status = Column(String(255)) # TODO(vish): enum?
@@ -333,8 +337,11 @@ class ExportDevice(BASE, NovaBase):
shelf_id = Column(Integer)
blade_id = Column(Integer)
volume_id = Column(Integer, ForeignKey('volumes.id'), nullable=True)
- volume = relationship(Volume, backref=backref('export_device',
- uselist=False))
+ volume = relationship(Volume,
+ backref=backref('export_device', uselist=False),
+ foreign_keys=volume_id,
+ primaryjoin='and_(ExportDevice.volume_id==Volume.id,'
+ 'ExportDevice.deleted==False)')
class KeyPair(BASE, NovaBase):
@@ -407,8 +414,12 @@ class NetworkIndex(BASE, NovaBase):
id = Column(Integer, primary_key=True)
index = Column(Integer, unique=True)
network_id = Column(Integer, ForeignKey('networks.id'), nullable=True)
- network = relationship(Network, backref=backref('network_index',
- uselist=False))
+ network = relationship(Network,
+ backref=backref('network_index', uselist=False),
+ foreign_keys=network_id,
+ primaryjoin='and_(NetworkIndex.network_id==Network.id,'
+ 'NetworkIndex.deleted==False)')
+
class AuthToken(BASE, NovaBase):
"""Represents an authorization token for all API transactions. Fields
@@ -432,8 +443,11 @@ class FixedIp(BASE, NovaBase):
network_id = Column(Integer, ForeignKey('networks.id'), nullable=True)
network = relationship(Network, backref=backref('fixed_ips'))
instance_id = Column(Integer, ForeignKey('instances.id'), nullable=True)
- instance = relationship(Instance, backref=backref('fixed_ip',
- uselist=False))
+ instance = relationship(Instance,
+ backref=backref('fixed_ip', uselist=False),
+ foreign_keys=instance_id,
+ primaryjoin='and_(FixedIp.instance_id==Instance.id,'
+ 'FixedIp.deleted==False)')
allocated = Column(Boolean, default=False)
leased = Column(Boolean, default=False)
reserved = Column(Boolean, default=False)
@@ -462,8 +476,11 @@ class FloatingIp(BASE, NovaBase):
id = Column(Integer, primary_key=True)
address = Column(String(255))
fixed_ip_id = Column(Integer, ForeignKey('fixed_ips.id'), nullable=True)
- fixed_ip = relationship(FixedIp, backref=backref('floating_ips'))
-
+ fixed_ip = relationship(FixedIp,
+ backref=backref('floating_ips'),
+ foreign_keys=fixed_ip_id,
+ primaryjoin='and_(FloatingIp.fixed_ip_id==FixedIp.id,'
+ 'FloatingIp.deleted==False)')
project_id = Column(String(255))
host = Column(String(255)) # , ForeignKey('hosts.id'))