diff options
author | Jenkins <jenkins@review.openstack.org> | 2012-09-18 20:24:43 +0000 |
---|---|---|
committer | Gerrit Code Review <review@openstack.org> | 2012-09-18 20:24:43 +0000 |
commit | 1b1fae700dc86870f5dfb81e668f02ab7b2c2929 (patch) | |
tree | e66f7e541fa723b0fc4efab9dd90cbe951f63a4b /nova | |
parent | 1db2f54e0bc2d9ac3b8140ff71b6f87e1f92a1cd (diff) | |
parent | 82d33f51f0fa2258f2a8d4003520af560d8bef11 (diff) | |
download | nova-1b1fae700dc86870f5dfb81e668f02ab7b2c2929.tar.gz nova-1b1fae700dc86870f5dfb81e668f02ab7b2c2929.tar.xz nova-1b1fae700dc86870f5dfb81e668f02ab7b2c2929.zip |
Merge "Correct db migration 91"
Diffstat (limited to 'nova')
-rw-r--r-- | nova/db/sqlalchemy/migrate_repo/versions/091_convert_volume_ids_to_uuid.py | 83 | ||||
-rw-r--r-- | nova/tests/test_migrations.py | 133 |
2 files changed, 210 insertions, 6 deletions
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 diff --git a/nova/tests/test_migrations.py b/nova/tests/test_migrations.py index 9487443a2..73b50c280 100644 --- a/nova/tests/test_migrations.py +++ b/nova/tests/test_migrations.py @@ -323,3 +323,136 @@ class TestMigrations(test.TestCase): migration_api.upgrade(engine, TestMigrations.REPOSITORY, 98) migration_api.downgrade(engine, TestMigrations.REPOSITORY, 97) + + def test_migration_91(self): + """Test that migration 91 works correctly. + + This test prevents regression of bugs 1052244 and 1052220. + """ + for key, engine in self.engines.items(): + migration_api.version_control(engine, TestMigrations.REPOSITORY, + migration.INIT_VERSION) + migration_api.upgrade(engine, TestMigrations.REPOSITORY, 90) + + vol1_id = '10' + vol1_uuid = '9db3c2e5-8cac-4e94-9e6c-b5f750736727' + + vol2_id = '11' + vol2_uuid = 'fb17fb5a-ca3d-4bba-8903-fc776ea81d78' + + snap_id = '7' + snap_uuid = 'a87e5108-8a2b-4c89-be96-0e8760db2c6a' + + inst_id = '0ec45d38-aefd-4c42-a209-361e848240b7' + + metadata = sqlalchemy.schema.MetaData() + metadata.bind = engine + + instances = sqlalchemy.Table('instances', metadata, autoload=True) + volumes = sqlalchemy.Table('volumes', metadata, autoload=True) + sm_flavors = sqlalchemy.Table( + 'sm_flavors', metadata, autoload=True) + sm_backend_config = sqlalchemy.Table( + 'sm_backend_config', metadata, autoload=True) + sm_volume = sqlalchemy.Table( + 'sm_volume', metadata, autoload=True) + volume_mappings = sqlalchemy.Table( + 'volume_id_mappings', metadata, autoload=True) + iscsi_targets = sqlalchemy.Table( + 'iscsi_targets', metadata, autoload=True) + volume_metadata = sqlalchemy.Table( + 'volume_metadata', metadata, autoload=True) + snapshots = sqlalchemy.Table('snapshots', metadata, autoload=True) + snapshot_mappings = sqlalchemy.Table( + 'snapshot_id_mappings', metadata, autoload=True) + block_device_mapping = sqlalchemy.Table( + 'block_device_mapping', metadata, autoload=True) + + volumes.insert().values(id=vol1_id).execute() + volume_mappings.insert() \ + .values(id=vol1_id, uuid=vol1_uuid).execute() + snapshots.insert().values(id=snap_id, volume_id=vol1_id).execute() + snapshot_mappings.insert() \ + .values(id=snap_id, uuid=snap_uuid).execute() + volumes.insert().values(id=vol2_id, snapshot_id=snap_id).execute() + volume_mappings.insert() \ + .values(id=vol2_id, uuid=vol2_uuid).execute() + sm_flavors.insert().values(id=7).execute() + sm_backend_config.insert().values(id=7, flavor_id=7).execute() + sm_volume.insert().values(id=vol1_id, backend_id=7).execute() + volume_metadata.insert().values(id=7, volume_id=vol1_id).execute() + iscsi_targets.insert().values(id=7, volume_id=vol1_id).execute() + instances.insert().values(id=7, uuid=inst_id).execute() + block_device_mapping.insert()\ + .values(id=7, volume_id=vol1_id, instance_uuid=inst_id) \ + .execute() + + vols = volumes.select().execute().fetchall() + self.assertEqual(set([vol.id for vol in vols]), + set([vol1_id, vol2_id])) + self.assertEqual(snap_id, vols[1].snapshot_id) + + query = volume_metadata.select(volume_metadata.c.id == 7) + self.assertEqual(vol1_id, query.execute().fetchone().volume_id) + + query = iscsi_targets.select(iscsi_targets.c.id == 7) + self.assertEqual(vol1_id, query.execute().fetchone().volume_id) + + query = block_device_mapping.select(block_device_mapping.c.id == 7) + self.assertEqual(vol1_id, query.execute().fetchone().volume_id) + + snaps = sqlalchemy.select([snapshots.c.id]).execute().fetchall() + self.assertEqual(set([snap.id for snap in snaps]), + set([snap_id])) + + sm_vols = sqlalchemy.select([sm_volume.c.id]).execute().fetchall() + self.assertEqual(set([sm_vol.id for sm_vol in sm_vols]), + set([vol1_id])) + + migration_api.upgrade(engine, TestMigrations.REPOSITORY, 91) + + vols = volumes.select().execute().fetchall() + self.assertEqual(set([vol.id for vol in vols]), + set([vol1_uuid, vol2_uuid])) + self.assertEqual(snap_uuid, vols[1].snapshot_id) + + query = volume_metadata.select(volume_metadata.c.id == 7) + self.assertEqual(vol1_uuid, query.execute().fetchone().volume_id) + + query = iscsi_targets.select(iscsi_targets.c.id == 7) + self.assertEqual(vol1_uuid, query.execute().fetchone().volume_id) + + query = block_device_mapping.select(block_device_mapping.c.id == 7) + self.assertEqual(vol1_uuid, query.execute().fetchone().volume_id) + + snaps = sqlalchemy.select([snapshots.c.id]).execute().fetchall() + self.assertEqual(set([snap.id for snap in snaps]), + set([snap_uuid])) + + sm_vols = sqlalchemy.select([sm_volume.c.id]).execute().fetchall() + self.assertEqual(set([sm_vol.id for sm_vol in sm_vols]), + set([vol1_uuid])) + + migration_api.downgrade(engine, TestMigrations.REPOSITORY, 90) + + vols = volumes.select().execute().fetchall() + self.assertEqual(set([vol.id for vol in vols]), + set([vol1_id, vol2_id])) + self.assertEqual(snap_id, vols[1].snapshot_id) + + query = volume_metadata.select(volume_metadata.c.id == 7) + self.assertEqual(vol1_id, query.execute().fetchone().volume_id) + + query = iscsi_targets.select(iscsi_targets.c.id == 7) + self.assertEqual(vol1_id, query.execute().fetchone().volume_id) + + query = block_device_mapping.select(block_device_mapping.c.id == 7) + self.assertEqual(vol1_id, query.execute().fetchone().volume_id) + + snaps = sqlalchemy.select([snapshots.c.id]).execute().fetchall() + self.assertEqual(set([snap.id for snap in snaps]), + set([snap_id])) + + sm_vols = sqlalchemy.select([sm_volume.c.id]).execute().fetchall() + self.assertEqual(set([sm_vol.id for sm_vol in sm_vols]), + set([vol1_id])) |