summaryrefslogtreecommitdiffstats
path: root/nova/db
diff options
context:
space:
mode:
authorJohn Griffith <john.griffith@solidfire.com>2012-05-04 11:31:56 -0600
committerJohn Griffith <john.griffith@solidfire.com>2012-05-10 13:36:32 -0600
commitdcad314fb9713104f0029311c43907e362ec6d49 (patch)
tree4e6fffab1e7f064e94cee264192d05269ad1c0d4 /nova/db
parentd9ed81222048f589b6863aaf2a99983ba5a3094f (diff)
downloadnova-dcad314fb9713104f0029311c43907e362ec6d49.tar.gz
nova-dcad314fb9713104f0029311c43907e362ec6d49.tar.xz
nova-dcad314fb9713104f0029311c43907e362ec6d49.zip
Remove instance Foreign Key in volumes table, replace with instance_uuid
* Remove the instance relationship and instance_id FK * Add instance_uuuid column to volumes table * Passed unit tests and devstack tests Change-Id: Id598f1f1d7915d1af6bf3dd75e5819dce08aaa0f
Diffstat (limited to 'nova/db')
-rw-r--r--nova/db/api.py9
-rw-r--r--nova/db/sqlalchemy/api.py32
-rw-r--r--nova/db/sqlalchemy/migrate_repo/versions/095_change_fk_instance_id_to_uuid.py94
-rw-r--r--nova/db/sqlalchemy/migrate_repo/versions/095_sqlite_downgrade.sql133
-rw-r--r--nova/db/sqlalchemy/migrate_repo/versions/095_sqlite_upgrade.sql132
-rw-r--r--nova/db/sqlalchemy/models.py7
6 files changed, 373 insertions, 34 deletions
diff --git a/nova/db/api.py b/nova/db/api.py
index 93eea8f10..ca1e420d7 100644
--- a/nova/db/api.py
+++ b/nova/db/api.py
@@ -986,9 +986,9 @@ def volume_get_all_by_host(context, host):
return IMPL.volume_get_all_by_host(context, host)
-def volume_get_all_by_instance(context, instance_id):
+def volume_get_all_by_instance_uuid(context, instance_uuid):
"""Get all volumes belonging to a instance."""
- return IMPL.volume_get_all_by_instance(context, instance_id)
+ return IMPL.volume_get_all_by_instance_uuid(context, instance_uuid)
def volume_get_all_by_project(context, project_id):
@@ -1001,11 +1001,6 @@ def volume_get_by_ec2_id(context, ec2_id):
return IMPL.volume_get_by_ec2_id(context, ec2_id)
-def volume_get_instance(context, volume_id):
- """Get the instance that a volume is attached to."""
- return IMPL.volume_get_instance(context, volume_id)
-
-
def volume_get_iscsi_target_num(context, volume_id):
"""Get the target num (tid) allocated to the volume."""
return IMPL.volume_get_iscsi_target_num(context, volume_id)
diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py
index 46e080578..f6af98d68 100644
--- a/nova/db/sqlalchemy/api.py
+++ b/nova/db/sqlalchemy/api.py
@@ -1374,7 +1374,6 @@ def _build_instance_get(context, session=None):
project_only=True).\
options(joinedload_all('security_groups.rules')).\
options(joinedload('info_cache')).\
- options(joinedload('volumes')).\
options(joinedload('metadata')).\
options(joinedload('instance_type'))
@@ -2402,15 +2401,17 @@ def volume_allocate_iscsi_target(context, volume_id, host):
@require_admin_context
-def volume_attached(context, volume_id, instance_id, mountpoint):
+def volume_attached(context, volume_id, instance_uuid, mountpoint):
+ if not utils.is_uuid_like(instance_uuid):
+ raise exception.InvalidUUID(instance_uuid)
+
session = get_session()
with session.begin():
volume_ref = volume_get(context, volume_id, session=session)
volume_ref['status'] = 'in-use'
volume_ref['mountpoint'] = mountpoint
volume_ref['attach_status'] = 'attached'
- volume_ref.instance = instance_get(context, instance_id,
- session=session)
+ volume_ref['instance_uuid'] = instance_uuid
volume_ref.save(session=session)
@@ -2471,7 +2472,7 @@ def volume_detached(context, volume_id):
volume_ref['status'] = 'available'
volume_ref['mountpoint'] = None
volume_ref['attach_status'] = 'detached'
- volume_ref.instance = None
+ volume_ref['instance_uuid'] = None
volume_ref.save(session=session)
@@ -2479,9 +2480,8 @@ def volume_detached(context, volume_id):
def _volume_get_query(context, session=None, project_only=False):
return model_query(context, models.Volume, session=session,
project_only=project_only).\
- options(joinedload('instance')).\
- options(joinedload('volume_metadata')).\
- options(joinedload('volume_type'))
+ options(joinedload('volume_metadata')).\
+ options(joinedload('volume_type'))
@require_context
@@ -2519,15 +2519,15 @@ def volume_get_all_by_host(context, host):
@require_admin_context
-def volume_get_all_by_instance(context, instance_id):
+def volume_get_all_by_instance_uuid(context, instance_uuid):
result = model_query(context, models.Volume, read_deleted="no").\
options(joinedload('volume_metadata')).\
options(joinedload('volume_type')).\
- filter_by(instance_id=instance_id).\
+ filter_by(instance_uuid=instance_uuid).\
all()
if not result:
- raise exception.VolumeNotFoundForInstance(instance_id=instance_id)
+ return []
return result
@@ -2539,16 +2539,6 @@ def volume_get_all_by_project(context, project_id):
@require_admin_context
-def volume_get_instance(context, volume_id):
- result = _volume_get_query(context).filter_by(id=volume_id).first()
-
- if not result:
- raise exception.VolumeNotFound(volume_id=volume_id)
-
- return result.instance
-
-
-@require_admin_context
def volume_get_iscsi_target_num(context, volume_id):
result = model_query(context, models.IscsiTarget, read_deleted="yes").\
filter_by(volume_id=volume_id).\
diff --git a/nova/db/sqlalchemy/migrate_repo/versions/095_change_fk_instance_id_to_uuid.py b/nova/db/sqlalchemy/migrate_repo/versions/095_change_fk_instance_id_to_uuid.py
new file mode 100644
index 000000000..ea8684f3d
--- /dev/null
+++ b/nova/db/sqlalchemy/migrate_repo/versions/095_change_fk_instance_id_to_uuid.py
@@ -0,0 +1,94 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2012 OpenStack LLC.
+# Copyright 2012 SolidFire 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.
+
+from sqlalchemy import select, Column
+from sqlalchemy import MetaData, Integer, String, Table
+from migrate import ForeignKeyConstraint
+
+from nova import log as logging
+
+
+LOG = logging.getLogger(__name__)
+
+
+def upgrade(migrate_engine):
+ meta = MetaData()
+ meta.bind = migrate_engine
+
+ instances = Table('instances', meta, autoload=True)
+ volumes = Table('volumes', meta, autoload=True)
+ instance_uuid_column = Column('instance_uuid', String(36))
+
+ instance_uuid_column.create(volumes)
+ try:
+ volumes.update().values(
+ instance_uuid=select(
+ [instances.c.uuid],
+ instances.c.id == volumes.c.instance_id)
+ ).execute()
+ except Exception:
+ instance_uuid_column.drop()
+
+ fkeys = list(volumes.c.instance_id.foreign_keys)
+ if fkeys:
+ try:
+ fk_name = fkeys[0].constraint.name
+ ForeignKeyConstraint(
+ columns=[volumes.c.instance_id],
+ refcolumns=[instances.c.id],
+ name=fk_name).drop()
+
+ except Exception:
+ LOG.error(_("foreign key could not be dropped"))
+ raise
+
+ volumes.c.instance_id.drop()
+
+
+def downgrade(migrate_engine):
+ meta = MetaData()
+ meta.bind = migrate_engine
+
+ instances = Table('instances', meta, autoload=True)
+ volumes = Table('volumes', meta, autoload=True)
+ instance_id_column = Column('instance_id', Integer)
+
+ instance_id_column.create(volumes)
+ try:
+ volumes.update().values(
+ instance_id=select(
+ [instances.c.id],
+ instances.c.uuid == volumes.c.instance_uuid)
+ ).execute()
+ except Exception:
+ instance_id_column.drop()
+
+ fkeys = list(volumes.c.instance_id.foreign_keys)
+ if fkeys:
+ try:
+ fk_name = fkeys[0].constraint.name
+ ForeignKeyConstraint(
+ columns=[volumes.c.instance_id],
+ refcolumns=[instances.c.id],
+ name=fk_name).create()
+
+ except Exception:
+ LOG.error(_("foreign key could not be created"))
+ raise
+
+ volumes.c.instance_uuid.drop()
diff --git a/nova/db/sqlalchemy/migrate_repo/versions/095_sqlite_downgrade.sql b/nova/db/sqlalchemy/migrate_repo/versions/095_sqlite_downgrade.sql
new file mode 100644
index 000000000..7c13455e4
--- /dev/null
+++ b/nova/db/sqlalchemy/migrate_repo/versions/095_sqlite_downgrade.sql
@@ -0,0 +1,133 @@
+BEGIN TRANSACTION;
+ -- change instance_id volumes table
+ CREATE TABLE volumes_backup(
+ created_at DATETIME,
+ updated_at DATETIME,
+ deleted_at DATETIME,
+ deleted BOOLEAN,
+ id VARCHAR(36) NOT NULL,
+ ec2_id INTEGER,
+ user_id VARCHAR(255),
+ project_id VARCHAR(255),
+ snapshot_id VARCHAR(36),
+ host VARCHAR(255),
+ size INTEGER,
+ availability_zone VARCHAR(255),
+ instance_id INTEGER,
+ instance_uuid VARCHAR(36),
+ mountpoint VARCHAR(255),
+ attach_time VARCHAR(255),
+ status VARCHAR(255),
+ attach_status VARCHAR(255),
+ scheduled_at DATETIME,
+ launched_at DATETIME,
+ terminated_at DATETIME,
+ display_name VARCHAR(255),
+ display_description VARCHAR(255),
+ provider_location VARCHAR(255),
+ provider_auth VARCHAR(255),
+ volume_type_id INTEGER,
+ PRIMARY KEY (id),
+ FOREIGN KEY(instance_id) REFERENCES instances (id),
+ UNIQUE (id),
+ CHECK (deleted IN (0, 1))
+ );
+
+ INSERT INTO volumes_backup SELECT
+ created_at,
+ updated_at,
+ deleted_at,
+ deleted,
+ id,
+ ec2_id,
+ user_id,
+ project_id,
+ snapshot_id,
+ host,
+ size,
+ availability_zone,
+ NULL,
+ instance_uuid,
+ mountpoint,
+ attach_time,
+ status,
+ attach_status,
+ scheduled_at,
+ launched_at,
+ terminated_at,
+ display_name,
+ display_description,
+ provider_location,
+ provider_auth,
+ volume_type_id
+ FROM volumes;
+
+ UPDATE volumes_backup
+ SET instance_id =
+ (SELECT id
+ FROM instances
+ WHERE volumes_backup.instance_uuid = instances.uuid
+ );
+ DROP TABLE volumes;
+
+ CREATE TABLE volumes(
+ created_at DATETIME,
+ updated_at DATETIME,
+ deleted_at DATETIME,
+ deleted BOOLEAN,
+ id VARCHAR(36) NOT NULL,
+ ec2_id INTEGER,
+ user_id VARCHAR(255),
+ project_id VARCHAR(255),
+ snapshot_id VARCHAR(36),
+ host VARCHAR(255),
+ size INTEGER,
+ availability_zone VARCHAR(255),
+ instance_id INTEGER,
+ mountpoint VARCHAR(255),
+ attach_time VARCHAR(255),
+ status VARCHAR(255),
+ attach_status VARCHAR(255),
+ scheduled_at DATETIME,
+ launched_at DATETIME,
+ terminated_at DATETIME,
+ display_name VARCHAR(255),
+ display_description VARCHAR(255),
+ provider_location VARCHAR(255),
+ provider_auth VARCHAR(255),
+ volume_type_id INTEGER,
+ PRIMARY KEY (id),
+ FOREIGN KEY (instance_id) REFERENCES instances (id),
+ UNIQUE (id),
+ CHECK (deleted IN (0, 1))
+ );
+
+ INSERT INTO volumes
+ SELECT created_at,
+ updated_at,
+ deleted_at,
+ deleted,
+ id,
+ ec2_id,
+ user_id,
+ project_id,
+ snapshot_id,
+ host,
+ size,
+ availability_zone,
+ instance_id,
+ mountpoint,
+ attach_time,
+ status,
+ attach_status,
+ scheduled_at,
+ launched_at,
+ terminated_at,
+ display_name,
+ display_description,
+ provider_location,
+ provider_auth,
+ volume_type_id
+ FROM volumes_backup;
+ DROP TABLE volumes_backup;
+COMMIT;
diff --git a/nova/db/sqlalchemy/migrate_repo/versions/095_sqlite_upgrade.sql b/nova/db/sqlalchemy/migrate_repo/versions/095_sqlite_upgrade.sql
new file mode 100644
index 000000000..130e11030
--- /dev/null
+++ b/nova/db/sqlalchemy/migrate_repo/versions/095_sqlite_upgrade.sql
@@ -0,0 +1,132 @@
+BEGIN TRANSACTION;
+ -- change instance_id volumes table
+ CREATE TABLE volumes_backup(
+ created_at DATETIME,
+ updated_at DATETIME,
+ deleted_at DATETIME,
+ deleted BOOLEAN,
+ id VARCHAR(36) NOT NULL,
+ ec2_id INTEGER,
+ user_id VARCHAR(255),
+ project_id VARCHAR(255),
+ snapshot_id VARCHAR(36),
+ host VARCHAR(255),
+ size INTEGER,
+ availability_zone VARCHAR(255),
+ instance_id INTEGER,
+ instance_uuid VARCHAR(36),
+ mountpoint VARCHAR(255),
+ attach_time VARCHAR(255),
+ status VARCHAR(255),
+ attach_status VARCHAR(255),
+ scheduled_at DATETIME,
+ launched_at DATETIME,
+ terminated_at DATETIME,
+ display_name VARCHAR(255),
+ display_description VARCHAR(255),
+ provider_location VARCHAR(255),
+ provider_auth VARCHAR(255),
+ volume_type_id INTEGER,
+ PRIMARY KEY (id),
+ FOREIGN KEY(instance_id) REFERENCES instances (id),
+ UNIQUE (id),
+ CHECK (deleted IN (0, 1))
+ );
+
+ INSERT INTO volumes_backup SELECT
+ created_at,
+ updated_at,
+ deleted_at,
+ deleted,
+ id,
+ ec2_id,
+ user_id,
+ project_id,
+ snapshot_id,
+ host,
+ size,
+ availability_zone,
+ instance_id,
+ NULL,
+ mountpoint,
+ attach_time,
+ status,
+ attach_status,
+ scheduled_at,
+ launched_at,
+ terminated_at,
+ display_name,
+ display_description,
+ provider_location,
+ provider_auth,
+ volume_type_id
+ FROM volumes;
+
+ UPDATE volumes_backup
+ SET instance_uuid =
+ (SELECT uuid
+ FROM instances
+ WHERE volumes_backup.instance_id = instances.id
+ );
+ DROP TABLE volumes;
+
+ CREATE TABLE volumes(
+ created_at DATETIME,
+ updated_at DATETIME,
+ deleted_at DATETIME,
+ deleted BOOLEAN,
+ id VARCHAR(36) NOT NULL,
+ ec2_id INTEGER,
+ user_id VARCHAR(255),
+ project_id VARCHAR(255),
+ snapshot_id VARCHAR(36),
+ host VARCHAR(255),
+ size INTEGER,
+ availability_zone VARCHAR(255),
+ instance_uuid VARCHAR(36),
+ mountpoint VARCHAR(255),
+ attach_time VARCHAR(255),
+ status VARCHAR(255),
+ attach_status VARCHAR(255),
+ scheduled_at DATETIME,
+ launched_at DATETIME,
+ terminated_at DATETIME,
+ display_name VARCHAR(255),
+ display_description VARCHAR(255),
+ provider_location VARCHAR(255),
+ provider_auth VARCHAR(255),
+ volume_type_id INTEGER,
+ PRIMARY KEY (id),
+ UNIQUE (id),
+ CHECK (deleted IN (0, 1))
+ );
+
+ INSERT INTO volumes
+ SELECT created_at,
+ updated_at,
+ deleted_at,
+ deleted,
+ id,
+ ec2_id,
+ user_id,
+ project_id,
+ snapshot_id,
+ host,
+ size,
+ availability_zone,
+ instance_uuid,
+ mountpoint,
+ attach_time,
+ status,
+ attach_status,
+ scheduled_at,
+ launched_at,
+ terminated_at,
+ display_name,
+ display_description,
+ provider_location,
+ provider_auth,
+ volume_type_id
+ FROM volumes_backup;
+ DROP TABLE volumes_backup;
+COMMIT;
diff --git a/nova/db/sqlalchemy/models.py b/nova/db/sqlalchemy/models.py
index 9007de424..056ecd411 100644
--- a/nova/db/sqlalchemy/models.py
+++ b/nova/db/sqlalchemy/models.py
@@ -341,12 +341,7 @@ class Volume(BASE, NovaBase):
host = Column(String(255)) # , ForeignKey('hosts.id'))
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'),
- foreign_keys=instance_id,
- primaryjoin='and_(Volume.instance_id==Instance.id,'
- 'Volume.deleted==False)')
+ instance_uuid = Column(String(36))
mountpoint = Column(String(255))
attach_time = Column(String(255)) # TODO(vish): datetime
status = Column(String(255)) # TODO(vish): enum?