Add PostgreSQL support to test migrations.

This commit adds support for running the migrations tests
with a PostgreSQL backend.

Migration 012 was changed because PostgreSQL's constraint
drop uses a different name to identify the foreign key
to be removed. The migration now handles it properly for
both postgres and mysql.

Change-Id: Ie8850608fc5f4bccda57a0b12c3b4adc8d1f61d0
This commit is contained in:
Matthew Treinish 2013-02-19 10:05:19 -05:00
parent 70907328ea
commit 2b180a2b6d
3 changed files with 52 additions and 18 deletions

View File

@ -41,11 +41,12 @@ def upgrade(migrate_engine):
t_images = _get_table('images', meta)
t_image_members = _get_table('image_members', meta)
t_image_properties = _get_table('image_properties', meta)
if migrate_engine.url.get_dialect().name == "sqlite":
dialect = migrate_engine.url.get_dialect().name
if dialect == "sqlite":
_upgrade_sqlite(t_images, t_image_members, t_image_properties)
_update_all_ids_to_uuids(t_images, t_image_members, t_image_properties)
else:
_upgrade_other(t_images, t_image_members, t_image_properties)
_upgrade_other(t_images, t_image_members, t_image_properties, dialect)
def downgrade(migrate_engine):
@ -57,12 +58,13 @@ def downgrade(migrate_engine):
t_images = _get_table('images', meta)
t_image_members = _get_table('image_members', meta)
t_image_properties = _get_table('image_properties', meta)
if migrate_engine.url.get_dialect().name == "sqlite":
dialect = migrate_engine.url.get_dialect().name
if dialect == "sqlite":
_update_all_uuids_to_ids(t_images, t_image_members, t_image_properties)
_downgrade_sqlite(t_images, t_image_members, t_image_properties)
else:
_downgrade_other(t_images, t_image_members, t_image_properties)
_downgrade_other(t_images, t_image_members, t_image_properties,
dialect)
def _upgrade_sqlite(t_images, t_image_members, t_image_properties):
@ -205,13 +207,13 @@ def _downgrade_sqlite(t_images, t_image_members, t_image_properties):
_sqlite_table_swap(t_image_members, t_image_properties, t_images)
def _upgrade_other(t_images, t_image_members, t_image_properties):
def _upgrade_other(t_images, t_image_members, t_image_properties, dialect):
"""
Upgrade 011 -> 012 with logic for non-SQLite databases.
"""
foreign_keys = _get_foreign_keys(t_images,
t_image_members,
t_image_properties)
t_image_properties, dialect)
for fk in foreign_keys:
fk.drop()
@ -226,13 +228,13 @@ def _upgrade_other(t_images, t_image_members, t_image_properties):
fk.create()
def _downgrade_other(t_images, t_image_members, t_image_properties):
def _downgrade_other(t_images, t_image_members, t_image_properties, dialect):
"""
Downgrade 012 -> 011 with logic for non-SQLite databases.
"""
foreign_keys = _get_foreign_keys(t_images,
t_image_members,
t_image_properties)
t_image_properties, dialect)
for fk in foreign_keys:
fk.drop()
@ -265,23 +267,29 @@ def _get_table(table_name, metadata):
return sqlalchemy.Table(table_name, metadata, autoload=True)
def _get_foreign_keys(t_images, t_image_members, t_image_properties):
def _get_foreign_keys(t_images, t_image_members, t_image_properties, dialect):
"""Retrieve and return foreign keys for members/properties tables."""
foreign_keys = []
if t_image_members.foreign_keys:
img_members_fk_name = list(t_image_members.foreign_keys)[0].name
fk1 = migrate.ForeignKeyConstraint([t_image_members.c.image_id],
[t_images.c.id],
name=img_members_fk_name)
if dialect == 'mysql':
fk1 = migrate.ForeignKeyConstraint([t_image_members.c.image_id],
[t_images.c.id],
name=img_members_fk_name)
else:
fk1 = migrate.ForeignKeyConstraint([t_image_members.c.image_id],
[t_images.c.id])
foreign_keys.append(fk1)
if t_image_properties.foreign_keys:
img_properties_fk_name = list(t_image_properties.foreign_keys)[0].name
fk2 = migrate.ForeignKeyConstraint([t_image_properties.c.image_id],
[t_images.c.id],
name=img_properties_fk_name)
if dialect == 'mysql':
fk2 = migrate.ForeignKeyConstraint([t_image_properties.c.image_id],
[t_images.c.id],
name=img_properties_fk_name)
else:
fk2 = migrate.ForeignKeyConstraint([t_image_properties.c.image_id],
[t_images.c.id])
foreign_keys.append(fk2)
return foreign_keys

View File

@ -64,6 +64,8 @@ def _get_connect_string(backend,
"""
if backend == "mysql":
backend = "mysql+mysqldb"
elif backend == "postgres":
backend = "postgresql+psycopg2"
return ("%(backend)s://%(user)s:%(passwd)s@localhost/%(database)s"
% locals())
@ -268,6 +270,29 @@ class TestMigrations(utils.BaseTestCase):
self.assertEqual(count, 0, "%d non InnoDB tables created" % count)
connection.close()
def test_postgresql_connect_fail(self):
"""
Test that we can trigger a postgres connection failure and we fail
gracefully to ensure we don't break people without postgres
"""
if _is_backend_avail('postgresql', user="openstack_cifail"):
self.fail("Shouldn't have connected")
def test_postgresql_opportunistically(self):
# Test postgresql database migration walk
if not _is_backend_avail('postgres'):
self.skipTest("postgresql not available")
# add this to the global lists to make reset work with it, it's removed
# automatically in tearDown so no need to clean it up here.
connect_string = _get_connect_string("postgres")
engine = sqlalchemy.create_engine(connect_string)
self.engines["postgresqlcitest"] = engine
self.test_databases["postgresqlcitest"] = connect_string
# build a fully populated postgresql database with all the tables
self._reset_databases()
self._walk_versions(engine, False, False)
def _walk_versions(self, engine=None, snake_walk=False, downgrade=True,
initial_version=None):
# Determine latest version script from the repo, then

View File

@ -19,5 +19,6 @@ testtools>=0.9.22
# Optional packages that should be installed when testing
MySQL-python
psycopg2
pysendfile==2.0.0
xattr>=0.6.0