Merge "db: Compact Ocata database migrations"

This commit is contained in:
Zuul
2021-02-08 00:31:55 +00:00
committed by Gerrit Code Review
17 changed files with 4 additions and 483 deletions

View File

@@ -1,23 +0,0 @@
# 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.
# This is a placeholder for backports.
# Do not use this number for new work. New work starts after
# all the placeholders.
#
# See this for more information:
# http://lists.openstack.org/pipermail/openstack-dev/2013-March/006827.html
def upgrade(migrate_engine):
pass

View File

@@ -1,23 +0,0 @@
# 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.
# This is a placeholder for backports.
# Do not use this number for new work. New work starts after
# all the placeholders.
#
# See this for more information:
# http://lists.openstack.org/pipermail/openstack-dev/2013-March/006827.html
def upgrade(migrate_engine):
pass

View File

@@ -1,23 +0,0 @@
# 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.
# This is a placeholder for backports.
# Do not use this number for new work. New work starts after
# all the placeholders.
#
# See this for more information:
# http://lists.openstack.org/pipermail/openstack-dev/2013-March/006827.html
def upgrade(migrate_engine):
pass

View File

@@ -1,23 +0,0 @@
# 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.
# This is a placeholder for backports.
# Do not use this number for new work. New work starts after
# all the placeholders.
#
# See this for more information:
# http://lists.openstack.org/pipermail/openstack-dev/2013-March/006827.html
def upgrade(migrate_engine):
pass

View File

@@ -1,23 +0,0 @@
# 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.
# This is a placeholder for backports.
# Do not use this number for new work. New work starts after
# all the placeholders.
#
# See this for more information:
# http://lists.openstack.org/pipermail/openstack-dev/2013-March/006827.html
def upgrade(migrate_engine):
pass

View File

@@ -1,23 +0,0 @@
# 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.
# This is a placeholder for backports.
# Do not use this number for new work. New work starts after
# all the placeholders.
#
# See this for more information:
# http://lists.openstack.org/pipermail/openstack-dev/2013-March/006827.html
def upgrade(migrate_engine):
pass

View File

@@ -1,23 +0,0 @@
# 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.
# This is a placeholder for backports.
# Do not use this number for new work. New work starts after
# all the placeholders.
#
# See this for more information:
# http://lists.openstack.org/pipermail/openstack-dev/2013-March/006827.html
def upgrade(migrate_engine):
pass

View File

@@ -1,23 +0,0 @@
# 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.
# This is a placeholder for backports.
# Do not use this number for new work. New work starts after
# all the placeholders.
#
# See this for more information:
# http://lists.openstack.org/pipermail/openstack-dev/2013-March/006827.html
def upgrade(migrate_engine):
pass

View File

@@ -1,23 +0,0 @@
# 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.
# This is a placeholder for backports.
# Do not use this number for new work. New work starts after
# all the placeholders.
#
# See this for more information:
# http://lists.openstack.org/pipermail/openstack-dev/2013-March/006827.html
def upgrade(migrate_engine):
pass

View File

@@ -1,23 +0,0 @@
# 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.
# This is a placeholder for backports.
# Do not use this number for new work. New work starts after
# all the placeholders.
#
# See this for more information:
# http://lists.openstack.org/pipermail/openstack-dev/2013-March/006827.html
def upgrade(migrate_engine):
pass

View File

@@ -1,68 +0,0 @@
# 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.
# This is a placeholder for backports.
# Do not use this number for new work. New work starts after
# all the placeholders.
#
# See this for more information:
# http://lists.openstack.org/pipermail/openstack-dev/2013-March/006827.html
from sqlalchemy import MetaData, Table, func, select
from nova import exception
from nova.i18n import _
def upgrade(migrate_engine):
meta = MetaData(migrate_engine)
instance_types = Table('instance_types', meta, autoload=True)
keypairs = Table('key_pairs', meta, autoload=True)
aggregates = Table('aggregates', meta, autoload=True)
instance_groups = Table('instance_groups', meta, autoload=True)
base_msg = _('Migration cannot continue until all these have '
'been migrated to the api database. Please run '
'`nova-manage db online_data_migrations\' on Newton '
'code before continuing.')
count = select([func.count()]).select_from(instance_types).where(
instance_types.c.deleted == 0).scalar()
if count:
msg = (base_msg +
_(' There are still %(count)i unmigrated flavors. ') % {
'count': count})
raise exception.ValidationError(detail=msg)
count = select([func.count()]).select_from(keypairs).where(
keypairs.c.deleted == 0).scalar()
if count:
msg = (base_msg +
_(' There are still %(count)i unmigrated keypairs. ') % {
'count': count})
raise exception.ValidationError(detail=msg)
count = select([func.count()]).select_from(aggregates).where(
aggregates.c.deleted == 0).scalar()
if count:
msg = (base_msg +
_(' There are still %(count)i unmigrated aggregates. ') % {
'count': count})
raise exception.ValidationError(detail=msg)
count = select([func.count()]).select_from(instance_groups).where(
instance_groups.c.deleted == 0).scalar()
if count:
msg = (base_msg +
_(' There are still %(count)i unmigrated instance groups. ') % {
'count': count})
raise exception.ValidationError(detail=msg)

View File

@@ -1,29 +0,0 @@
# Copyright 2016 Intel Corporation
# 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.
from sqlalchemy import MetaData, Table
def upgrade(migrate_engine):
meta = MetaData(bind=migrate_engine)
column_name = 'scheduled_at'
# Remove scheduled_at column from instances table
instances = Table('instances', meta, autoload=True)
shadow_instances = Table('shadow_instances', meta, autoload=True)
if hasattr(instances.c, column_name):
instances.drop_column(instances.c[column_name])
if hasattr(shadow_instances.c, column_name):
shadow_instances.drop_column(shadow_instances.c[column_name])

View File

@@ -1,56 +0,0 @@
# 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.
from oslo_log import log as logging
from sqlalchemy import MetaData, Table, Index
from sqlalchemy.engine import reflection
LOG = logging.getLogger(__name__)
INDEX_COLUMNS_1 = ['project_id']
INDEX_NAME_1 = 'instances_project_id_idx'
INDEX_COLUMNS_2 = ['updated_at', 'project_id']
INDEX_NAME_2 = 'instances_updated_at_project_id_idx'
TABLE_NAME = 'instances'
def _get_table_index(migrate_engine, table_name, index_columns):
inspector = reflection.Inspector.from_engine(migrate_engine)
for idx in inspector.get_indexes(table_name):
if idx['column_names'] == index_columns:
break
else:
idx = None
return idx
def upgrade(migrate_engine):
meta = MetaData()
meta.bind = migrate_engine
table = Table(TABLE_NAME, meta, autoload=True)
if _get_table_index(migrate_engine, TABLE_NAME, INDEX_COLUMNS_1):
LOG.info('Skipped adding %s because an equivalent index'
' already exists.', INDEX_NAME_1)
else:
columns = [getattr(table.c, col_name) for col_name in INDEX_COLUMNS_1]
index = Index(INDEX_NAME_1, *columns)
index.create(migrate_engine)
if _get_table_index(migrate_engine, TABLE_NAME, INDEX_COLUMNS_2):
LOG.info('Skipped adding %s because an equivalent index'
' already exists.', INDEX_NAME_2)
else:
columns = [getattr(table.c, col_name) for col_name in INDEX_COLUMNS_2]
index = Index(INDEX_NAME_2, *columns)
index.create(migrate_engine)

View File

@@ -633,7 +633,6 @@ def upgrade(migrate_engine):
Column('host', String(length=255)),
Column('user_data', MediumText()),
Column('reservation_id', String(length=255)),
Column('scheduled_at', DateTime),
Column('launched_at', DateTime),
Column('terminated_at', DateTime),
Column('display_name', String(length=255)),
@@ -1334,6 +1333,9 @@ def upgrade(migrate_engine):
instances.c.project_id, instances.c.deleted),
Index('instances_deleted_created_at_idx',
instances.c.deleted, instances.c.created_at),
Index('instances_project_id_idx', instances.c.project_id),
Index('instances_updated_at_project_id_idx',
instances.c.updated_at, instances.c.project_id),
# instance_actions
Index('instance_uuid_idx', instance_actions.c.instance_uuid),

View File

@@ -29,7 +29,7 @@ from nova import exception
from nova.i18n import _
INIT_VERSION = {}
INIT_VERSION['main'] = 333
INIT_VERSION['main'] = 346
INIT_VERSION['api'] = 0
_REPOSITORY = {}

View File

@@ -163,7 +163,6 @@ class NovaMigrationsCheckers(test_migrations.ModelsMigrationsSync,
self.INIT_VERSION + 1,
]
newton_placeholders = list(range(335, 345))
ocata_placeholders = list(range(348, 358))
pike_placeholders = list(range(363, 373))
queens_placeholders = list(range(379, 389))
@@ -176,7 +175,6 @@ class NovaMigrationsCheckers(test_migrations.ModelsMigrationsSync,
victoria_placeholders = list(range(413, 418))
return (special +
newton_placeholders +
ocata_placeholders +
pike_placeholders +
queens_placeholders +
@@ -200,11 +198,6 @@ class NovaMigrationsCheckers(test_migrations.ModelsMigrationsSync,
exceptions = [
# The base migration can do whatever it likes
self.INIT_VERSION + 1,
# 346 Drops column scheduled_at from instances table since it
# is no longer used. The field value is always NULL so
# it does not affect anything.
346,
]
# Reviewers: DO NOT ALLOW THINGS TO BE ADDED HERE
@@ -243,22 +236,6 @@ class NovaMigrationsCheckers(test_migrations.ModelsMigrationsSync,
def test_walk_versions(self):
self.walk_versions(snake_walk=False, downgrade=False)
def _check_345(self, engine, data):
# NOTE(danms): Just a sanity-check migration
pass
def _check_346(self, engine, data):
self.assertColumnNotExists(engine, 'instances', 'scheduled_at')
self.assertColumnNotExists(engine, 'shadow_instances', 'scheduled_at')
def _check_347(self, engine, data):
self.assertIndexMembers(engine, 'instances',
'instances_project_id_idx',
['project_id'])
self.assertIndexMembers(engine, 'instances',
'instances_updated_at_project_id_idx',
['updated_at', 'project_id'])
def _check_358(self, engine, data):
self.assertColumnExists(engine, 'block_device_mapping',
'attachment_id')

View File

@@ -233,81 +233,6 @@ class TestGetEngine(test.NoDBTestCase):
mock_get_engine.assert_called_once_with()
class TestOcataCheck(test.TestCase):
def setUp(self):
super(TestOcataCheck, self).setUp()
self.context = context.get_admin_context()
self.migration = importlib.import_module(
'nova.db.sqlalchemy.migrate_repo.versions.'
'345_require_online_migration_completion')
self.engine = db_api.get_engine()
self.flavor_values = {
'name': 'foo',
'memory_mb': 256,
'vcpus': 1,
'root_gb': 10,
'ephemeral_gb': 100,
'flavorid': 'bar',
'swap': 1,
'rxtx_factor': 1.0,
'vcpu_weight': 1,
'disabled': False,
'is_public': True,
'deleted': 0
}
self.keypair_values = {
'name': 'foo',
'user_ud': 'bar',
'fingerprint': 'baz',
'public_key': 'bat',
'type': 'ssh',
}
self.aggregate_values = {
'uuid': uuidsentinel.agg,
'name': 'foo',
}
self.ig_values = {
'user_id': 'foo',
'project_id': 'bar',
'uuid': uuidsentinel.ig,
'name': 'baz',
'deleted': 0
}
def test_upgrade_clean(self):
self.migration.upgrade(self.engine)
def test_upgrade_dirty_flavors(self):
flavors = db_utils.get_table(self.engine, 'instance_types')
flavors.insert().execute(self.flavor_values)
self.assertRaises(exception.ValidationError,
self.migration.upgrade, self.engine)
def test_upgrade_dirty_keypairs(self):
db_api.key_pair_create(self.context, self.keypair_values)
self.assertRaises(exception.ValidationError,
self.migration.upgrade, self.engine)
def test_upgrade_with_deleted_keypairs(self):
keypair = db_api.key_pair_create(self.context, self.keypair_values)
db_api.key_pair_destroy(self.context,
keypair['user_id'], keypair['name'])
self.migration.upgrade(self.engine)
def test_upgrade_dirty_instance_groups(self):
igs = db_utils.get_table(self.engine, 'instance_groups')
igs.insert().execute(self.ig_values)
self.assertRaises(exception.ValidationError,
self.migration.upgrade, self.engine)
def test_upgrade_with_deleted_instance_groups(self):
igs = db_utils.get_table(self.engine, 'instance_groups')
group_id = igs.insert().execute(self.ig_values).inserted_primary_key[0]
igs.update().where(igs.c.id == group_id).values(
deleted=group_id).execute()
self.migration.upgrade(self.engine)
class TestNewtonCellsCheck(test.NoDBTestCase):
USES_DB_SELF = True