From 82d33f51f0fa2258f2a8d4003520af560d8bef11 Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Mon, 17 Sep 2012 13:25:31 -0700 Subject: Correct db migration 91 * Snapshot.id gets the new snapshot uuid rather than snapshot.volume_id * Foreign keys are dropped before and recreated after updating id fields * Snapshot id <-> uuid queries use snapshot_id_mappings.c.id rather than volume_id_mappings.id * Snapshot id <-> uuid queries are executed before passing the new id values into subsequent UPDATE queries * Thoroughly inspect the expected modifications in a new functional test * Fixes bug 1052244 * Fixes bug 1052220 Change-Id: I22c820e5747562251c6447ac678c80dd9e0e2e20 --- .../versions/091_convert_volume_ids_to_uuid.py | 83 ++++++++++++++++++++-- 1 file changed, 77 insertions(+), 6 deletions(-) (limited to 'nova/db') diff --git a/nova/db/sqlalchemy/migrate_repo/versions/091_convert_volume_ids_to_uuid.py b/nova/db/sqlalchemy/migrate_repo/versions/091_convert_volume_ids_to_uuid.py index 3c4183f68..3938107da 100644 --- a/nova/db/sqlalchemy/migrate_repo/versions/091_convert_volume_ids_to_uuid.py +++ b/nova/db/sqlalchemy/migrate_repo/versions/091_convert_volume_ids_to_uuid.py @@ -15,6 +15,7 @@ # License for the specific language governing permissions and limitations # under the License. +from migrate import ForeignKeyConstraint from sqlalchemy import MetaData, select, Table from nova.openstack.common import log as logging @@ -38,10 +39,31 @@ def upgrade(migrate_engine): volume_mappings = Table('volume_id_mappings', meta, autoload=True) snapshot_mappings = Table('snapshot_id_mappings', meta, autoload=True) + fkey_columns = [ + iscsi_targets.c.volume_id, + volume_metadata.c.volume_id, + sm_volumes.c.id, + ] + for column in fkey_columns: + fkeys = list(column.foreign_keys) + if fkeys: + fkey_name = fkeys[0].constraint.name + LOG.info('Dropping foreign key %s' % fkey_name) + fkey = ForeignKeyConstraint(columns=[column], + refcolumns=[volumes.c.id], + name=fkey_name) + try: + fkey.drop() + except Exception: + if migrate_engine.url.get_dialect().name.startswith('sqlite'): + pass + else: + raise + volume_list = list(volumes.select().execute()) for v in volume_list: new_id = select([volume_mappings.c.uuid], - volume_mappings.c.id == v['id']) + volume_mappings.c.id == v['id']).execute().fetchone()[0] volumes.update().\ where(volumes.c.id == v['id']).\ @@ -70,7 +92,7 @@ def upgrade(migrate_engine): snapshot_list = list(snapshots.select().execute()) for s in snapshot_list: new_id = select([snapshot_mappings.c.uuid], - volume_mappings.c.id == s['id']) + snapshot_mappings.c.id == s['id']).execute().fetchone()[0] volumes.update().\ where(volumes.c.snapshot_id == s['id']).\ @@ -78,12 +100,26 @@ def upgrade(migrate_engine): snapshots.update().\ where(snapshots.c.id == s['id']).\ - values(volume_id=new_id).execute() + values(id=new_id).execute() block_device_mapping.update().\ where(block_device_mapping.c.snapshot_id == s['id']).\ values(snapshot_id=new_id).execute() + for column in fkey_columns: + fkeys = list(column.foreign_keys) + if fkeys: + fkey = ForeignKeyConstraint(columns=[column], + refcolumns=[volumes.c.id]) + try: + fkey.create() + LOG.info('Created foreign key %s' % fkey_name) + except Exception: + if migrate_engine.url.get_dialect().name.startswith('sqlite'): + pass + else: + raise + def downgrade(migrate_engine): """Convert volume and snapshot id columns back to int.""" @@ -100,10 +136,31 @@ def downgrade(migrate_engine): volume_mappings = Table('volume_id_mappings', meta, autoload=True) snapshot_mappings = Table('snapshot_id_mappings', meta, autoload=True) + fkey_columns = [ + iscsi_targets.c.volume_id, + volume_metadata.c.volume_id, + sm_volumes.c.id, + ] + for column in fkey_columns: + fkeys = list(column.foreign_keys) + if fkeys: + fkey_name = fkeys[0].constraint.name + LOG.info('Dropping foreign key %s' % fkey_name) + fkey = ForeignKeyConstraint(columns=[column], + refcolumns=[volumes.c.id], + name=fkey_name) + try: + fkey.drop() + except Exception: + if migrate_engine.url.get_dialect().name.startswith('sqlite'): + pass + else: + raise + volume_list = list(volumes.select().execute()) for v in volume_list: new_id = select([volume_mappings.c.id], - volume_mappings.c.uuid == v['id']) + volume_mappings.c.uuid == v['id']).execute().fetchone()[0] volumes.update().\ where(volumes.c.id == v['id']).\ @@ -132,7 +189,7 @@ def downgrade(migrate_engine): snapshot_list = list(snapshots.select().execute()) for s in snapshot_list: new_id = select([snapshot_mappings.c.id], - volume_mappings.c.uuid == s['id']) + snapshot_mappings.c.uuid == s['id']).execute().fetchone()[0] volumes.update().\ where(volumes.c.snapshot_id == s['id']).\ @@ -140,8 +197,22 @@ def downgrade(migrate_engine): snapshots.update().\ where(snapshots.c.id == s['id']).\ - values(volume_id=new_id).execute() + values(id=new_id).execute() block_device_mapping.update().\ where(block_device_mapping.c.snapshot_id == s['id']).\ values(snapshot_id=new_id).execute() + + for column in fkey_columns: + fkeys = list(column.foreign_keys) + if fkeys: + fkey = ForeignKeyConstraint(columns=[column], + refcolumns=[volumes.c.id]) + try: + fkey.create() + LOG.info('Created foreign key %s' % fkey_name) + except Exception: + if migrate_engine.url.get_dialect().name.startswith('sqlite'): + pass + else: + raise -- cgit