diff options
| author | John Griffith <john.griffith@solidfire.com> | 2012-05-04 11:31:56 -0600 |
|---|---|---|
| committer | John Griffith <john.griffith@solidfire.com> | 2012-05-10 13:36:32 -0600 |
| commit | dcad314fb9713104f0029311c43907e362ec6d49 (patch) | |
| tree | 4e6fffab1e7f064e94cee264192d05269ad1c0d4 /nova/db | |
| parent | d9ed81222048f589b6863aaf2a99983ba5a3094f (diff) | |
| download | nova-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.py | 9 | ||||
| -rw-r--r-- | nova/db/sqlalchemy/api.py | 32 | ||||
| -rw-r--r-- | nova/db/sqlalchemy/migrate_repo/versions/095_change_fk_instance_id_to_uuid.py | 94 | ||||
| -rw-r--r-- | nova/db/sqlalchemy/migrate_repo/versions/095_sqlite_downgrade.sql | 133 | ||||
| -rw-r--r-- | nova/db/sqlalchemy/migrate_repo/versions/095_sqlite_upgrade.sql | 132 | ||||
| -rw-r--r-- | nova/db/sqlalchemy/models.py | 7 |
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? |
