diff --git a/nova/db/api/migrations/versions/cdeec0c85668_drop_legacy_migrate_version_table.py b/nova/db/api/migrations/versions/cdeec0c85668_drop_legacy_migrate_version_table.py new file mode 100644 index 0000000000..7299f0da4d --- /dev/null +++ b/nova/db/api/migrations/versions/cdeec0c85668_drop_legacy_migrate_version_table.py @@ -0,0 +1,36 @@ +# 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. + +"""Drop legacy migrate_version table + +Revision ID: cdeec0c85668 +Revises: b30f573d3377 +Create Date: 2023-02-01 17:04:52.984703 +""" + +from alembic import op +from sqlalchemy.engine import reflection + +# revision identifiers, used by Alembic. +revision = 'cdeec0c85668' +down_revision = 'b30f573d3377' +branch_labels = None +depends_on = None + + +def upgrade(): + conn = op.get_bind() + inspector = reflection.Inspector.from_engine(conn) + tables = inspector.get_table_names() + + if 'migrate_version' in tables: + op.drop_table('migrate_version') diff --git a/nova/db/main/api.py b/nova/db/main/api.py index 7d24f974f9..52f3210615 100644 --- a/nova/db/main/api.py +++ b/nova/db/main/api.py @@ -4508,12 +4508,9 @@ def archive_deleted_rows(context=None, max_rows=None, before=None, for table in meta.sorted_tables: tablename = table.name rows_archived = 0 - # skip the special sqlalchemy-migrate migrate_version table and any - # shadow tables - # TODO(stephenfin): Drop 'migrate_version' once we remove support for - # the legacy sqlalchemy-migrate migrations + # skip the special alembic_version version table and any shadow tables if ( - tablename in ('migrate_version', 'alembic_version') or + tablename == 'alembic_version' or tablename.startswith(_SHADOW_TABLE_PREFIX) ): continue @@ -4543,9 +4540,12 @@ def archive_deleted_rows(context=None, max_rows=None, before=None, def _purgeable_tables(metadata): - return [t for t in metadata.sorted_tables - if (t.name.startswith(_SHADOW_TABLE_PREFIX) and not - t.name.endswith('migrate_version'))] + return [ + t for t in metadata.sorted_tables if ( + t.name.startswith(_SHADOW_TABLE_PREFIX) and not + t.name == 'alembic_version' + ) + ] def purge_shadow_tables(context, before_date, status_fn=None): diff --git a/nova/db/main/migrations/versions/1b91788ec3a6_drop_legacy_migrate_version_table.py b/nova/db/main/migrations/versions/1b91788ec3a6_drop_legacy_migrate_version_table.py new file mode 100644 index 0000000000..804d45a130 --- /dev/null +++ b/nova/db/main/migrations/versions/1b91788ec3a6_drop_legacy_migrate_version_table.py @@ -0,0 +1,36 @@ +# 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. + +"""Drop legacy migrate_version table + +Revision ID: 1b91788ec3a6 +Revises: 960aac0e09ea +Create Date: 2023-02-01 16:46:24.206580 +""" + +from alembic import op +from sqlalchemy.engine import reflection + +# revision identifiers, used by Alembic. +revision = '1b91788ec3a6' +down_revision = '960aac0e09ea' +branch_labels = None +depends_on = None + + +def upgrade(): + conn = op.get_bind() + inspector = reflection.Inspector.from_engine(conn) + tables = inspector.get_table_names() + + if 'migrate_version' in tables: + op.drop_table('migrate_version') diff --git a/nova/tests/unit/db/api/test_migrations.py b/nova/tests/unit/db/api/test_migrations.py index 7c99f2f44a..3756520807 100644 --- a/nova/tests/unit/db/api/test_migrations.py +++ b/nova/tests/unit/db/api/test_migrations.py @@ -62,11 +62,6 @@ class NovaModelsMigrationsSync(test_migrations.ModelsMigrationsSync): def include_object(self, object_, name, type_, reflected, compare_to): if type_ == 'table': - # migrate_version is a sqlalchemy-migrate control table and - # isn't included in the model. - if name == 'migrate_version': - return False - # Define a whitelist of tables that will be removed from the DB in # a later release and don't have a corresponding model anymore. @@ -196,6 +191,11 @@ class NovaMigrationsWalk( for removed_column in self._b30f573d3377_removed_columns: self.assertNotIn(removed_column, columns) + def _check_cdeec0c85668(self, connection): + # the table optionally existed: there's no way to check for its + # removal without creating it first, which is dumb + pass + def test_single_base_revision(self): """Ensure we only have a single base revision. diff --git a/nova/tests/unit/db/main/test_migrations.py b/nova/tests/unit/db/main/test_migrations.py index 579888cfd2..d74efc7398 100644 --- a/nova/tests/unit/db/main/test_migrations.py +++ b/nova/tests/unit/db/main/test_migrations.py @@ -79,11 +79,9 @@ class NovaModelsMigrationsSync(test_migrations.ModelsMigrationsSync): def include_object(self, object_, name, type_, reflected, compare_to): if type_ == 'table': - # migrate_version is a sqlalchemy-migrate control table and - # isn't included in the model. shadow_* are generated from - # the model and have their own tests to ensure they don't - # drift. - if name == 'migrate_version' or name.startswith('shadow_'): + # shadow_* are generated from the model and have their own tests to + # ensure they don't drift. + if name.startswith('shadow_'): return False # Define a whitelist of tables that will be removed from the DB in @@ -157,7 +155,6 @@ class TestModelsSyncMySQL( "FROM information_schema.TABLES " "WHERE TABLE_SCHEMA = :database " "AND ENGINE != 'InnoDB' " - "AND TABLE_NAME != 'migrate_version'" ), {'database': self.engine.url.database}, ) @@ -281,6 +278,11 @@ class NovaMigrationsWalk( connection, 'instances', 'uuid', ) + def _check_1b91788ec3a6(self, connection): + # the table optionally existed: there's no way to check for its + # removal without creating it first, which is dumb + pass + def test_single_base_revision(self): """Ensure we only have a single base revision.