From 2cf06e9ab471e9bcaa5ba954224f006607197b4b Mon Sep 17 00:00:00 2001 From: Gordon Chung Date: Thu, 6 Feb 2014 18:41:44 -0500 Subject: [PATCH] Alembic migrations not tested take alembic migrations out until we can confidently make the switch to it once real db tests are set up. Closes-Bug: #1217156 Change-Id: Ic62c5248dc92a0a0eb497b6f278d42070606abe9 --- .../17738166b91_fix_meter_resource_m.py | 50 ------ .../versions/2c3ccda5a3ad_fix_uniq_name.py | 69 -------- .../43b1a023dfaa_add_column_repeat_al.py | 41 ----- .../b6ae66d05e3_remove_extra_indexes.py | 94 ----------- .../versions/028_alembic_migrations.py | 154 ++++++++++++++++++ ceilometer/storage/sqlalchemy/migration.py | 3 - 6 files changed, 154 insertions(+), 257 deletions(-) delete mode 100644 ceilometer/storage/sqlalchemy/alembic/versions/17738166b91_fix_meter_resource_m.py delete mode 100644 ceilometer/storage/sqlalchemy/alembic/versions/2c3ccda5a3ad_fix_uniq_name.py delete mode 100644 ceilometer/storage/sqlalchemy/alembic/versions/43b1a023dfaa_add_column_repeat_al.py delete mode 100644 ceilometer/storage/sqlalchemy/alembic/versions/b6ae66d05e3_remove_extra_indexes.py create mode 100644 ceilometer/storage/sqlalchemy/migrate_repo/versions/028_alembic_migrations.py diff --git a/ceilometer/storage/sqlalchemy/alembic/versions/17738166b91_fix_meter_resource_m.py b/ceilometer/storage/sqlalchemy/alembic/versions/17738166b91_fix_meter_resource_m.py deleted file mode 100644 index 5aba1afc2..000000000 --- a/ceilometer/storage/sqlalchemy/alembic/versions/17738166b91_fix_meter_resource_m.py +++ /dev/null @@ -1,50 +0,0 @@ -# -*- encoding: utf-8 -*- -# -# Authors: Svetlana Shturm -# -# 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. -"""fix_meter_resource_metadata_type - -Revision ID: 17738166b91 -Revises: 43b1a023dfaa -Create Date: 2013-08-08 11:20:56.514012 - -""" - -# revision identifiers, used by Alembic. -revision = '17738166b91' -down_revision = '43b1a023dfaa' - -from alembic import op -import sqlalchemy as sa - - -def change_type(type): - column_old = 'resource_metadata' - column_new = column_old + '_new' - bind = op.get_bind() - meta = sa.MetaData(bind.engine) - meter = sa.Table('meter', meta, autoload=True) - new_column = sa.Column(column_new, type) - new_column.create(meter) - meter.update().values(resource_metadata_new=meter.c[column_old]).execute() - meter.c[column_old].drop() - meter.c[column_new].alter(name=column_old) - - -def upgrade(): - change_type(sa.Text) - - -def downgrade(): - change_type(sa.String(5000)) diff --git a/ceilometer/storage/sqlalchemy/alembic/versions/2c3ccda5a3ad_fix_uniq_name.py b/ceilometer/storage/sqlalchemy/alembic/versions/2c3ccda5a3ad_fix_uniq_name.py deleted file mode 100644 index fa8cc144c..000000000 --- a/ceilometer/storage/sqlalchemy/alembic/versions/2c3ccda5a3ad_fix_uniq_name.py +++ /dev/null @@ -1,69 +0,0 @@ -# -*- encoding: utf-8 -*- -# -# Copyright 2010-2011 OpenStack Foundation -# Copyright 2012-2013 IBM Corp. # -# -# Authors: Svetlana Shturm -# -# 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. -"""Fix name of UniqueConstraint according to OpenStack naming convention - -Revision ID: 2c3ccda5a3ad -Revises: b6ae66d05e3 -Create Date: 2013-08-19 18:06:03.409584 - -""" - -# revision identifiers, used by Alembic. -revision = '2c3ccda5a3ad' -down_revision = 'b6ae66d05e3' - -from alembic import op - - -TABLE_NAME = 'sourceassoc' -UNIQ_NAME = 'uniq_sourceassoc0meter_id0user_id' -COLUMNS = ('meter_id', 'user_id') - - -def change_uniq(table_name, uniq_name, columns, downgrade=False): - bind = op.get_bind() - engine = bind.engine - if engine.name == 'sqlite': - return - if engine.name == 'mysql': - # For mysql dialect all dependent FK should be removed - # before renaming of constraint. - op.drop_constraint('fk_sourceassoc_meter_id', - table_name, - type='foreignkey') - op.drop_constraint('fk_sourceassoc_user_id', - table_name, - type='foreignkey') - if downgrade: - op.drop_constraint(uniq_name, table_name=table_name, type='unique') - else: - op.create_unique_constraint(uniq_name, table_name, columns) - if engine.name == 'mysql': - op.create_foreign_key('fk_sourceassoc_meter_id', table_name, 'meter', - ['meter_id'], ['id']) - op.create_foreign_key('fk_sourceassoc_user_id', table_name, 'user', - ['user_id'], ['id']) - - -def upgrade(): - change_uniq(TABLE_NAME, UNIQ_NAME, COLUMNS) - - -def downgrade(): - change_uniq(TABLE_NAME, UNIQ_NAME, COLUMNS, downgrade=True) diff --git a/ceilometer/storage/sqlalchemy/alembic/versions/43b1a023dfaa_add_column_repeat_al.py b/ceilometer/storage/sqlalchemy/alembic/versions/43b1a023dfaa_add_column_repeat_al.py deleted file mode 100644 index e1ef27c7c..000000000 --- a/ceilometer/storage/sqlalchemy/alembic/versions/43b1a023dfaa_add_column_repeat_al.py +++ /dev/null @@ -1,41 +0,0 @@ -# -*- encoding: utf-8 -*- -# -# Copyright © 2013 eNovance -# -# Authors: Mehdi Abaakouk -# -# 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. -"""Add column repeat_alarms - -Revision ID: 43b1a023dfaa -Revises: None -Create Date: 2013-07-29 17:25:53.931326 - -""" - -# revision identifiers, used by Alembic. -revision = '43b1a023dfaa' -down_revision = None - -from alembic import op -import sqlalchemy as sa - - -def upgrade(): - op.add_column('alarm', sa.Column('repeat_actions', - sa.Boolean, - server_default=sa.sql.expression.false())) - - -def downgrade(): - op.drop_column('alarm', 'repeat_actions') diff --git a/ceilometer/storage/sqlalchemy/alembic/versions/b6ae66d05e3_remove_extra_indexes.py b/ceilometer/storage/sqlalchemy/alembic/versions/b6ae66d05e3_remove_extra_indexes.py deleted file mode 100644 index cce7e1255..000000000 --- a/ceilometer/storage/sqlalchemy/alembic/versions/b6ae66d05e3_remove_extra_indexes.py +++ /dev/null @@ -1,94 +0,0 @@ -# -*- encoding: utf-8 -*- -# -# Copyright 2010-2011 OpenStack Foundation -# Copyright 2012-2013 IBM Corp. # -# -# Authors: Svetlana Shturm -# -# 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. -"""Remove extra indexes - -Revision ID: b6ae66d05e3 -Revises: 17738166b91 -Create Date: 2013-08-19 15:54:43.529222 - -""" - -# revision identifiers, used by Alembic. -revision = 'b6ae66d05e3' -down_revision = '17738166b91' - -from alembic import op -import sqlalchemy as sa - - -INDEXES = ( - # ([dialects], table_name, index_name, create/delete, uniq/not_uniq, - # length_limited) - (['mysql', 'sqlite', 'postgresql'], - 'resource', - 'resource_user_id_project_id_key', - ('user_id', 'project_id'), True, False, True), - (['mysql'], 'source', 'id', ('id',), False, True, False)) - - -def index_cleanup(engine_names, table_name, uniq_name, columns, create, - unique, limited): - bind = op.get_bind() - engine = bind.engine - if engine.name not in engine_names: - return - if create: - if limited and engine.name == 'mysql': - # For some versions of mysql we can get an error - # "Specified key was too long; max key length is 1000 bytes". - # We should create an index by hand in this case with limited - # length of columns. - meta = sa.MetaData() - meta.bind = engine - table = sa.Table(table_name, meta, autoload=True) - columns_mysql = ",".join((c + "(100)" for c in columns)) - sql = ("create index %s ON %s (%s)" % (uniq_name, table, - columns_mysql)) - engine.execute(sql) - else: - op.create_index(uniq_name, table_name, columns, unique=unique) - else: - if unique: - op.drop_constraint(uniq_name, table_name, type='unique') - else: - op.drop_index(uniq_name, table_name=table_name) - - -def upgrade(): - for (engine_names, table_name, uniq_name, columns, create, uniq, - limited) in INDEXES: - index_cleanup(engine_names, - table_name, - uniq_name, - columns, - create, - uniq, - limited) - - -def downgrade(): - for (engine_names, table_name, uniq_name, columns, create, uniq, - limited) in INDEXES: - index_cleanup(engine_names, - table_name, - uniq_name, - columns, - not create, - uniq, - limited) diff --git a/ceilometer/storage/sqlalchemy/migrate_repo/versions/028_alembic_migrations.py b/ceilometer/storage/sqlalchemy/migrate_repo/versions/028_alembic_migrations.py new file mode 100644 index 000000000..b52769214 --- /dev/null +++ b/ceilometer/storage/sqlalchemy/migrate_repo/versions/028_alembic_migrations.py @@ -0,0 +1,154 @@ +# -*- encoding: utf-8 -*- +# +# Copyright 2014 OpenStack Foundation +# 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. +import migrate +import sqlalchemy as sa + + +def get_alembic_version(meta): + """Return Alembic version or None if no Alembic table exists.""" + try: + a_ver = sa.Table('alembic_version', meta, autoload=True) + return sa.select([a_ver.c.version_num]).scalar() + except sa.exc.NoSuchTableError: + return None + + +def delete_alembic(meta): + try: + sa.Table('alembic_version', meta, autoload=True).drop() + except sa.exc.NoSuchTableError: + pass + + +INDEXES = ( + # ([dialects], table_name, index_name, create/delete, uniq/not_uniq) + (['mysql', 'sqlite', 'postgresql'], + 'resource', + 'resource_user_id_project_id_key', + ('user_id', 'project_id'), True, False, True), + (['mysql'], 'source', 'id', ('id',), False, True, False)) + + +def index_cleanup(meta, engine_names, table_name, uniq_name, columns, + create, unique, limited): + table = sa.Table(table_name, meta, autoload=True) + if create: + if limited and meta.bind.engine.name == 'mysql': + # For some versions of mysql we can get an error + # "Specified key was too long; max key length is 1000 bytes". + # We should create an index by hand in this case with limited + # length of columns. + columns_mysql = ",".join((c + "(100)" for c in columns)) + sql = ("create index %s ON %s (%s)" % (uniq_name, table, + columns_mysql)) + meta.bind.engine.execute(sql) + else: + cols = [table.c[col] for col in columns] + sa.Index(uniq_name, *cols, unique=unique).create() + else: + if unique: + migrate.UniqueConstraint(*columns, table=table).drop() + else: + cols = [table.c[col] for col in columns] + sa.Index(uniq_name, *cols, unique=unique).drop() + + +def change_uniq(meta, downgrade=False): + uniq_name = 'uniq_sourceassoc0meter_id0user_id' + columns = ('meter_id', 'user_id') + + if meta.bind.engine.name == 'sqlite': + return + + sourceassoc = sa.Table('sourceassoc', meta, autoload=True) + meter = sa.Table('meter', meta, autoload=True) + user = sa.Table('user', meta, autoload=True) + if meta.bind.engine.name == 'mysql': + # For mysql dialect all dependent FK should be removed + # before renaming of constraint. + params = {'columns': [sourceassoc.c.meter_id], + 'refcolumns': [meter.c.id], + 'name': 'fk_sourceassoc_meter_id'} + migrate.ForeignKeyConstraint(**params).drop() + params = {'columns': [sourceassoc.c.user_id], + 'refcolumns': [user.c.id], + 'name': 'fk_sourceassoc_user_id'} + migrate.ForeignKeyConstraint(**params).drop() + if downgrade: + migrate.UniqueConstraint(*columns, table=sourceassoc, + name=uniq_name).drop() + else: + migrate.UniqueConstraint(*columns, table=sourceassoc, + name=uniq_name).create() + if meta.bind.engine.name == 'mysql': + params = {'columns': [sourceassoc.c.meter_id], + 'refcolumns': [meter.c.id], + 'name': 'fk_sourceassoc_meter_id'} + migrate.ForeignKeyConstraint(**params).create() + params = {'columns': [sourceassoc.c.user_id], + 'refcolumns': [user.c.id], + 'name': 'fk_sourceassoc_user_id'} + migrate.ForeignKeyConstraint(**params).create() + + +def upgrade(migrate_engine): + meta = sa.MetaData(bind=migrate_engine) + a_ver = get_alembic_version(meta) + + if not a_ver: + alarm = sa.Table('alarm', meta, autoload=True) + repeat_act = sa.Column('repeat_actions', sa.Boolean, + server_default=sa.sql.expression.false()) + alarm.create_column(repeat_act) + a_ver = '43b1a023dfaa' + + if a_ver == '43b1a023dfaa': + meter = sa.Table('meter', meta, autoload=True) + meter.c.resource_metadata.alter(type=sa.Text) + a_ver = '17738166b91' + + if a_ver == '17738166b91': + for (engine_names, table_name, uniq_name, + columns, create, uniq, limited) in INDEXES: + if migrate_engine in engine_names: + index_cleanup(meta, engine_names, table_name, uniq_name, + columns, create, uniq, limited) + a_ver = 'b6ae66d05e3' + + if a_ver == 'b6ae66d05e3': + change_uniq(meta) + + delete_alembic(meta) + + +def downgrade(migrate_engine): + meta = sa.MetaData(bind=migrate_engine) + + change_uniq(meta, downgrade=True) + + for (engine_names, table_name, uniq_name, + columns, create, uniq, limited) in INDEXES: + if migrate_engine in engine_names: + index_cleanup(meta, engine_names, table_name, uniq_name, + columns, not create, uniq, limited) + + meter = sa.Table('meter', meta, autoload=True) + meter.c.resource_metadata.alter(type=sa.String(5000)) + + alarm = sa.Table('alarm', meta, autoload=True) + repeat_act = sa.Column('repeat_actions', sa.Boolean) + alarm.drop_column(repeat_act) diff --git a/ceilometer/storage/sqlalchemy/migration.py b/ceilometer/storage/sqlalchemy/migration.py index 460207c98..159a59bda 100644 --- a/ceilometer/storage/sqlalchemy/migration.py +++ b/ceilometer/storage/sqlalchemy/migration.py @@ -17,9 +17,7 @@ import os -import alembic from alembic import config as alembic_config - from migrate import exceptions as versioning_exceptions from migrate.versioning import api as versioning_api from migrate.versioning.repository import Repository @@ -34,7 +32,6 @@ def db_sync(engine): versioning_api.upgrade(engine, repository) config = _alembic_config() config._engine = engine - alembic.command.upgrade(config, "head") def _alembic_config():