summaryrefslogtreecommitdiffstats
path: root/nova
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2012-09-18 20:24:43 +0000
committerGerrit Code Review <review@openstack.org>2012-09-18 20:24:43 +0000
commit1b1fae700dc86870f5dfb81e668f02ab7b2c2929 (patch)
treee66f7e541fa723b0fc4efab9dd90cbe951f63a4b /nova
parent1db2f54e0bc2d9ac3b8140ff71b6f87e1f92a1cd (diff)
parent82d33f51f0fa2258f2a8d4003520af560d8bef11 (diff)
downloadnova-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.py83
-rw-r--r--nova/tests/test_migrations.py133
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]))