db: Remove legacy migrations

sqlalchemy-migrate does not (and will not) support sqlalchemy 2.0. We
need to drop these migrations to ensure we can upgrade our sqlalchemy
version.

Change-Id: I7756e393b78296fb8dbf3ca69c759d75b816376d
Signed-off-by: Stephen Finucane <stephenfin@redhat.com>
This commit is contained in:
Stephen Finucane 2023-02-01 16:42:53 +00:00
parent f01a90ccb8
commit fd39e4b4be
59 changed files with 24 additions and 3537 deletions

View File

@ -24,6 +24,10 @@ Schema migrations
The database migration engine was changed from ``sqlalchemy-migrate`` to
``alembic``.
.. versionchanged:: 27.0.0 (Antelope)
The legacy ``sqlalchemy-migrate``-based database migrations were removed.
The `alembic`__ database migration tool is used to manage schema migrations in
nova. The migration files and related metadata can be found in
``nova/db/api/migrations`` (for the API database) and
@ -36,10 +40,10 @@ respectively.
.. note::
There are also legacy migrations provided in the ``legacy_migrations``
subdirectory for both the API and main databases. These are provided to
facilitate upgrades from pre-Xena (24.0.0) deployments and will be removed
in a future release. They should not be modified or extended.
There were also legacy migrations provided in the ``legacy_migrations``
subdirectory for both the API and main databases. These were provided to
facilitate upgrades from pre-Xena (24.0.0) deployments. They were removed
in the 27.0.0 (Antelope) release.
The best reference for alembic is the `alembic documentation`__, but a small
example is provided here. You can create the migration either manually or

View File

@ -1,4 +0,0 @@
This is a database migration repository.
More information at
http://code.google.com/p/sqlalchemy-migrate/

View File

@ -1,20 +0,0 @@
#!/usr/bin/env python
# Copyright 2012 OpenStack Foundation
#
# 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 migrate.versioning.shell import main
if __name__ == '__main__':
main(debug='False', repository='.')

View File

@ -1,20 +0,0 @@
[db_settings]
# Used to identify which repository this database is versioned under.
# You can use the name of your project.
repository_id=nova_api
# The name of the database table used to track the schema version.
# This name shouldn't already be used by your project.
# If this is changed once a database is under version control, you'll need to
# change the table name in each database too.
version_table=migrate_version
# When committing a change script, Migrate will attempt to generate the
# sql for all supported databases; normally, if one of them fails - probably
# because you don't have that database installed - it is ignored and the
# commit continues, perhaps ending successfully.
# Databases in this list MUST compile successfully during a commit, or the
# entire commit will fail. List the databases your application will actually
# be using to ensure your updates to that database work properly.
# This must be a list; example: ['postgres','sqlite']
required_dbs=[]

View File

@ -1,602 +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 migrate.changeset.constraint import ForeignKeyConstraint
from migrate import UniqueConstraint
import sqlalchemy as sa
from sqlalchemy import dialects
from nova.db import types
from nova.objects import keypair
def InetSmall():
return sa.String(length=39).with_variant(
dialects.postgresql.INET(), 'postgresql'
)
def upgrade(migrate_engine):
meta = sa.MetaData()
# NOTE(stephenfin): This is not compatible with SQLAlchemy 2.0 but neither
# is sqlalchemy-migrate which requires this. We'll remove these migrations
# when dropping SQLAlchemy < 2.x support
meta.bind = migrate_engine
cell_mappings = sa.Table('cell_mappings', meta,
sa.Column('created_at', sa.DateTime),
sa.Column('updated_at', sa.DateTime),
sa.Column('id', sa.Integer, primary_key=True, nullable=False),
sa.Column('uuid', sa.String(length=36), nullable=False),
sa.Column('name', sa.String(length=255)),
sa.Column('transport_url', sa.Text()),
sa.Column('database_connection', sa.Text()),
# NOTE(stephenfin): These were originally added by sqlalchemy-migrate
# which did not generate the constraints
sa.Column(
'disabled', sa.Boolean(create_constraint=False), default=False),
UniqueConstraint('uuid', name='uniq_cell_mappings0uuid'),
sa.Index('uuid_idx', 'uuid'),
mysql_engine='InnoDB',
mysql_charset='utf8'
)
host_mappings = sa.Table('host_mappings', meta,
sa.Column('created_at', sa.DateTime),
sa.Column('updated_at', sa.DateTime),
sa.Column('id', sa.Integer, primary_key=True, nullable=False),
sa.Column('cell_id', sa.Integer, nullable=False),
sa.Column('host', sa.String(length=255), nullable=False),
UniqueConstraint(
'host', name='uniq_host_mappings0host'),
sa.Index('host_idx', 'host'),
ForeignKeyConstraint(
columns=['cell_id'], refcolumns=[cell_mappings.c.id]),
mysql_engine='InnoDB',
mysql_charset='utf8'
)
instance_mappings = sa.Table('instance_mappings', meta,
sa.Column('created_at', sa.DateTime),
sa.Column('updated_at', sa.DateTime),
sa.Column('id', sa.Integer, primary_key=True, nullable=False),
sa.Column('instance_uuid', sa.String(length=36), nullable=False),
sa.Column('cell_id', sa.Integer, nullable=True),
sa.Column('project_id', sa.String(length=255), nullable=False),
# NOTE(stephenfin): These were originally added by sqlalchemy-migrate
# which did not generate the constraints
sa.Column(
'queued_for_delete', sa.Boolean(create_constraint=False),
default=False),
sa.Column('user_id', sa.String(length=255), nullable=True),
UniqueConstraint(
'instance_uuid', name='uniq_instance_mappings0instance_uuid'),
sa.Index('instance_uuid_idx', 'instance_uuid'),
sa.Index('project_id_idx', 'project_id'),
sa.Index(
'instance_mappings_user_id_project_id_idx', 'user_id',
'project_id'),
ForeignKeyConstraint(
columns=['cell_id'], refcolumns=[cell_mappings.c.id]),
mysql_engine='InnoDB',
mysql_charset='utf8'
)
flavors = sa.Table('flavors', meta,
sa.Column('created_at', sa.DateTime),
sa.Column('updated_at', sa.DateTime),
sa.Column('name', sa.String(length=255), nullable=False),
sa.Column('id', sa.Integer, primary_key=True, nullable=False),
sa.Column('memory_mb', sa.Integer, nullable=False),
sa.Column('vcpus', sa.Integer, nullable=False),
sa.Column('swap', sa.Integer, nullable=False),
sa.Column('vcpu_weight', sa.Integer),
sa.Column('flavorid', sa.String(length=255), nullable=False),
sa.Column('rxtx_factor', sa.Float),
sa.Column('root_gb', sa.Integer),
sa.Column('ephemeral_gb', sa.Integer),
sa.Column('disabled', sa.Boolean),
sa.Column('is_public', sa.Boolean),
sa.Column('description', sa.Text()),
UniqueConstraint('flavorid', name='uniq_flavors0flavorid'),
UniqueConstraint('name', name='uniq_flavors0name'),
mysql_engine='InnoDB',
mysql_charset='utf8'
)
flavor_extra_specs = sa.Table('flavor_extra_specs', meta,
sa.Column('created_at', sa.DateTime),
sa.Column('updated_at', sa.DateTime),
sa.Column('id', sa.Integer, primary_key=True, nullable=False),
sa.Column('flavor_id', sa.Integer, nullable=False),
sa.Column('key', sa.String(length=255), nullable=False),
sa.Column('value', sa.String(length=255)),
UniqueConstraint(
'flavor_id', 'key', name='uniq_flavor_extra_specs0flavor_id0key'),
sa.Index('flavor_extra_specs_flavor_id_key_idx', 'flavor_id', 'key'),
ForeignKeyConstraint(columns=['flavor_id'], refcolumns=[flavors.c.id]),
mysql_engine='InnoDB',
mysql_charset='utf8'
)
flavor_projects = sa.Table('flavor_projects', meta,
sa.Column('created_at', sa.DateTime),
sa.Column('updated_at', sa.DateTime),
sa.Column('id', sa.Integer, primary_key=True, nullable=False),
sa.Column('flavor_id', sa.Integer, nullable=False),
sa.Column('project_id', sa.String(length=255), nullable=False),
UniqueConstraint(
'flavor_id', 'project_id',
name='uniq_flavor_projects0flavor_id0project_id'),
ForeignKeyConstraint(
columns=['flavor_id'], refcolumns=[flavors.c.id]),
mysql_engine='InnoDB',
mysql_charset='utf8'
)
request_specs = sa.Table('request_specs', meta,
sa.Column('created_at', sa.DateTime),
sa.Column('updated_at', sa.DateTime),
sa.Column('id', sa.Integer, primary_key=True, nullable=False),
sa.Column('instance_uuid', sa.String(36), nullable=False),
sa.Column('spec', types.MediumText(), nullable=False),
UniqueConstraint(
'instance_uuid', name='uniq_request_specs0instance_uuid'),
sa.Index('request_spec_instance_uuid_idx', 'instance_uuid'),
mysql_engine='InnoDB',
mysql_charset='utf8'
)
build_requests = sa.Table('build_requests', meta,
sa.Column('created_at', sa.DateTime),
sa.Column('updated_at', sa.DateTime),
sa.Column('id', sa.Integer, primary_key=True, nullable=False),
sa.Column('request_spec_id', sa.Integer, nullable=True),
sa.Column('project_id', sa.String(length=255), nullable=False),
sa.Column('user_id', sa.String(length=255), nullable=True),
sa.Column('display_name', sa.String(length=255)),
sa.Column('instance_metadata', sa.Text),
sa.Column('progress', sa.Integer),
sa.Column('vm_state', sa.String(length=255)),
sa.Column('task_state', sa.String(length=255)),
sa.Column('image_ref', sa.String(length=255)),
sa.Column('access_ip_v4', InetSmall()),
sa.Column('access_ip_v6', InetSmall()),
sa.Column('info_cache', sa.Text),
sa.Column('security_groups', sa.Text, nullable=True),
sa.Column('config_drive', sa.Boolean, default=False, nullable=True),
sa.Column('key_name', sa.String(length=255)),
sa.Column(
'locked_by',
sa.Enum('owner', 'admin', name='build_requests0locked_by')),
sa.Column('instance_uuid', sa.String(length=36)),
sa.Column('instance', types.MediumText()),
sa.Column('block_device_mappings', types.MediumText()),
sa.Column('tags', sa.Text()),
UniqueConstraint(
'instance_uuid', name='uniq_build_requests0instance_uuid'),
sa.Index('build_requests_project_id_idx', 'project_id'),
sa.Index('build_requests_instance_uuid_idx', 'instance_uuid'),
mysql_engine='InnoDB',
mysql_charset='utf8'
)
keypairs = sa.Table('key_pairs', meta,
sa.Column('created_at', sa.DateTime),
sa.Column('updated_at', sa.DateTime),
sa.Column('id', sa.Integer, primary_key=True, nullable=False),
sa.Column('name', sa.String(255), nullable=False),
sa.Column('user_id', sa.String(255), nullable=False),
sa.Column('fingerprint', sa.String(255)),
sa.Column('public_key', sa.Text()),
sa.Column(
'type',
sa.Enum('ssh', 'x509', metadata=meta, name='keypair_types'),
nullable=False, server_default=keypair.KEYPAIR_TYPE_SSH),
UniqueConstraint(
'user_id', 'name', name='uniq_key_pairs0user_id0name'),
mysql_engine='InnoDB',
mysql_charset='utf8'
)
projects = sa.Table('projects', meta,
sa.Column(
'id', sa.Integer, primary_key=True, nullable=False,
autoincrement=True),
sa.Column('external_id', sa.String(length=255), nullable=False),
sa.Column('created_at', sa.DateTime),
sa.Column('updated_at', sa.DateTime),
UniqueConstraint('external_id', name='uniq_projects0external_id'),
mysql_engine='InnoDB',
mysql_charset='latin1',
)
users = sa.Table('users', meta,
sa.Column(
'id', sa.Integer, primary_key=True, nullable=False,
autoincrement=True),
sa.Column('external_id', sa.String(length=255), nullable=False),
sa.Column('created_at', sa.DateTime),
sa.Column('updated_at', sa.DateTime),
UniqueConstraint('external_id', name='uniq_users0external_id'),
mysql_engine='InnoDB',
mysql_charset='latin1',
)
resource_classes = sa.Table('resource_classes', meta,
sa.Column('id', sa.Integer, primary_key=True, nullable=False),
sa.Column('name', sa.String(length=255), nullable=False),
sa.Column('created_at', sa.DateTime),
sa.Column('updated_at', sa.DateTime),
UniqueConstraint('name', name='uniq_resource_classes0name'),
mysql_engine='InnoDB',
mysql_charset='latin1'
)
nameargs = {}
if migrate_engine.name == 'mysql':
nameargs['collation'] = 'utf8_bin'
resource_providers = sa.Table(
'resource_providers', meta,
sa.Column('created_at', sa.DateTime),
sa.Column('updated_at', sa.DateTime),
sa.Column('id', sa.Integer, primary_key=True, nullable=False),
sa.Column('uuid', sa.String(36), nullable=False),
sa.Column('name', sa.Unicode(200, **nameargs), nullable=True),
sa.Column('generation', sa.Integer, default=0),
sa.Column('can_host', sa.Integer, default=0),
sa.Column(
'root_provider_id', sa.Integer,
sa.ForeignKey('resource_providers.id')),
sa.Column(
'parent_provider_id', sa.Integer,
sa.ForeignKey('resource_providers.id')),
UniqueConstraint('uuid', name='uniq_resource_providers0uuid'),
UniqueConstraint('name', name='uniq_resource_providers0name'),
sa.Index('resource_providers_name_idx', 'name'),
sa.Index('resource_providers_uuid_idx', 'uuid'),
sa.Index(
'resource_providers_root_provider_id_idx', 'root_provider_id'),
sa.Index(
'resource_providers_parent_provider_id_idx', 'parent_provider_id'),
mysql_engine='InnoDB',
mysql_charset='latin1'
)
inventories = sa.Table(
'inventories', meta,
sa.Column('created_at', sa.DateTime),
sa.Column('updated_at', sa.DateTime),
sa.Column('id', sa.Integer, primary_key=True, nullable=False),
sa.Column('resource_provider_id', sa.Integer, nullable=False),
sa.Column('resource_class_id', sa.Integer, nullable=False),
sa.Column('total', sa.Integer, nullable=False),
sa.Column('reserved', sa.Integer, nullable=False),
sa.Column('min_unit', sa.Integer, nullable=False),
sa.Column('max_unit', sa.Integer, nullable=False),
sa.Column('step_size', sa.Integer, nullable=False),
sa.Column('allocation_ratio', sa.Float, nullable=False),
sa.Index(
'inventories_resource_provider_id_idx', 'resource_provider_id'),
sa.Index(
'inventories_resource_provider_resource_class_idx',
'resource_provider_id', 'resource_class_id'),
sa.Index(
'inventories_resource_class_id_idx', 'resource_class_id'),
UniqueConstraint(
'resource_provider_id', 'resource_class_id',
name='uniq_inventories0resource_provider_resource_class'),
mysql_engine='InnoDB',
mysql_charset='latin1'
)
traits = sa.Table(
'traits', meta,
sa.Column('created_at', sa.DateTime),
sa.Column('updated_at', sa.DateTime),
sa.Column(
'id', sa.Integer, primary_key=True, nullable=False,
autoincrement=True),
sa.Column('name', sa.Unicode(255, **nameargs), nullable=False),
UniqueConstraint('name', name='uniq_traits0name'),
mysql_engine='InnoDB',
mysql_charset='latin1',
)
allocations = sa.Table(
'allocations', meta,
sa.Column('created_at', sa.DateTime),
sa.Column('updated_at', sa.DateTime),
sa.Column('id', sa.Integer, primary_key=True, nullable=False),
sa.Column('resource_provider_id', sa.Integer, nullable=False),
sa.Column('consumer_id', sa.String(36), nullable=False),
sa.Column('resource_class_id', sa.Integer, nullable=False),
sa.Column('used', sa.Integer, nullable=False),
sa.Index(
'allocations_resource_provider_class_used_idx',
'resource_provider_id', 'resource_class_id', 'used'),
sa.Index(
'allocations_resource_class_id_idx', 'resource_class_id'),
sa.Index('allocations_consumer_id_idx', 'consumer_id'),
mysql_engine='InnoDB',
mysql_charset='latin1'
)
consumers = sa.Table(
'consumers', meta,
sa.Column('created_at', sa.DateTime),
sa.Column('updated_at', sa.DateTime),
sa.Column(
'id', sa.Integer, primary_key=True, nullable=False,
autoincrement=True),
sa.Column('uuid', sa.String(length=36), nullable=False),
sa.Column('project_id', sa.Integer, nullable=False),
sa.Column('user_id', sa.Integer, nullable=False),
sa.Column(
'generation', sa.Integer, default=0, server_default=sa.text('0'),
nullable=False),
sa.Index('consumers_project_id_uuid_idx', 'project_id', 'uuid'),
sa.Index(
'consumers_project_id_user_id_uuid_idx', 'project_id', 'user_id',
'uuid'),
UniqueConstraint('uuid', name='uniq_consumers0uuid'),
mysql_engine='InnoDB',
mysql_charset='latin1',
)
resource_provider_aggregates = sa.Table(
'resource_provider_aggregates', meta,
sa.Column('created_at', sa.DateTime),
sa.Column('updated_at', sa.DateTime),
sa.Column(
'resource_provider_id', sa.Integer, primary_key=True,
nullable=False),
sa.Column(
'aggregate_id', sa.Integer, primary_key=True, nullable=False),
sa.Index(
'resource_provider_aggregates_aggregate_id_idx', 'aggregate_id'),
mysql_engine='InnoDB',
mysql_charset='latin1'
)
resource_provider_traits = sa.Table(
'resource_provider_traits', meta,
sa.Column('created_at', sa.DateTime),
sa.Column('updated_at', sa.DateTime),
sa.Column(
'trait_id', sa.Integer, sa.ForeignKey('traits.id'),
primary_key=True, nullable=False),
sa.Column(
'resource_provider_id', sa.Integer, primary_key=True,
nullable=False),
sa.Index(
'resource_provider_traits_resource_provider_trait_idx',
'resource_provider_id', 'trait_id'),
ForeignKeyConstraint(
columns=['resource_provider_id'],
refcolumns=[resource_providers.c.id]),
mysql_engine='InnoDB',
mysql_charset='latin1',
)
placement_aggregates = sa.Table('placement_aggregates', meta,
sa.Column('created_at', sa.DateTime),
sa.Column('updated_at', sa.DateTime),
sa.Column('id', sa.Integer, primary_key=True, nullable=False),
sa.Column('uuid', sa.String(length=36), index=True),
UniqueConstraint('uuid', name='uniq_placement_aggregates0uuid'),
mysql_engine='InnoDB',
mysql_charset='latin1'
)
aggregates = sa.Table('aggregates', meta,
sa.Column('created_at', sa.DateTime),
sa.Column('updated_at', sa.DateTime),
sa.Column('id', sa.Integer, primary_key=True, nullable=False),
sa.Column('uuid', sa.String(length=36)),
sa.Column('name', sa.String(length=255)),
sa.Index('aggregate_uuid_idx', 'uuid'),
UniqueConstraint('name', name='uniq_aggregate0name'),
mysql_engine='InnoDB',
mysql_charset='utf8'
)
aggregate_hosts = sa.Table('aggregate_hosts', meta,
sa.Column('created_at', sa.DateTime),
sa.Column('updated_at', sa.DateTime),
sa.Column('id', sa.Integer, primary_key=True, nullable=False),
sa.Column('host', sa.String(length=255)),
sa.Column(
'aggregate_id', sa.Integer, sa.ForeignKey('aggregates.id'),
nullable=False),
UniqueConstraint(
'host', 'aggregate_id',
name='uniq_aggregate_hosts0host0aggregate_id'),
mysql_engine='InnoDB',
mysql_charset='utf8'
)
aggregate_metadata = sa.Table('aggregate_metadata', meta,
sa.Column('created_at', sa.DateTime),
sa.Column('updated_at', sa.DateTime),
sa.Column('id', sa.Integer, primary_key=True, nullable=False),
sa.Column(
'aggregate_id', sa.Integer, sa.ForeignKey('aggregates.id'),
nullable=False),
sa.Column('key', sa.String(length=255), nullable=False),
sa.Column('value', sa.String(length=255), nullable=False),
UniqueConstraint(
'aggregate_id', 'key',
name='uniq_aggregate_metadata0aggregate_id0key'),
sa.Index('aggregate_metadata_key_idx', 'key'),
mysql_engine='InnoDB',
mysql_charset='utf8'
)
groups = sa.Table('instance_groups', meta,
sa.Column('created_at', sa.DateTime),
sa.Column('updated_at', sa.DateTime),
sa.Column('id', sa.Integer, primary_key=True, nullable=False),
sa.Column('user_id', sa.String(length=255)),
sa.Column('project_id', sa.String(length=255)),
sa.Column('uuid', sa.String(length=36), nullable=False),
sa.Column('name', sa.String(length=255)),
UniqueConstraint(
'uuid', name='uniq_instance_groups0uuid'),
mysql_engine='InnoDB',
mysql_charset='utf8',
)
group_policy = sa.Table('instance_group_policy', meta,
sa.Column('created_at', sa.DateTime),
sa.Column('updated_at', sa.DateTime),
sa.Column('id', sa.Integer, primary_key=True, nullable=False),
sa.Column('policy', sa.String(length=255)),
sa.Column(
'group_id', sa.Integer, sa.ForeignKey('instance_groups.id'),
nullable=False),
sa.Column('rules', sa.Text),
sa.Index('instance_group_policy_policy_idx', 'policy'),
mysql_engine='InnoDB',
mysql_charset='utf8',
)
group_member = sa.Table('instance_group_member', meta,
sa.Column('created_at', sa.DateTime),
sa.Column('updated_at', sa.DateTime),
sa.Column('id', sa.Integer, primary_key=True, nullable=False),
sa.Column('instance_uuid', sa.String(length=255)),
sa.Column(
'group_id', sa.Integer, sa.ForeignKey('instance_groups.id'),
nullable=False),
sa.Index('instance_group_member_instance_idx', 'instance_uuid'),
mysql_engine='InnoDB',
mysql_charset='utf8',
)
quota_classes = sa.Table('quota_classes', meta,
sa.Column('created_at', sa.DateTime),
sa.Column('updated_at', sa.DateTime),
sa.Column('id', sa.Integer, primary_key=True, nullable=False),
sa.Column('class_name', sa.String(length=255)),
sa.Column('resource', sa.String(length=255)),
sa.Column('hard_limit', sa.Integer),
sa.Index('quota_classes_class_name_idx', 'class_name'),
mysql_engine='InnoDB',
mysql_charset='utf8',
)
quota_usages = sa.Table('quota_usages', meta,
sa.Column('created_at', sa.DateTime),
sa.Column('updated_at', sa.DateTime),
sa.Column('id', sa.Integer, primary_key=True, nullable=False),
sa.Column('project_id', sa.String(length=255)),
sa.Column('resource', sa.String(length=255), nullable=False),
sa.Column('in_use', sa.Integer, nullable=False),
sa.Column('reserved', sa.Integer, nullable=False),
sa.Column('until_refresh', sa.Integer),
sa.Column('user_id', sa.String(length=255)),
sa.Index('quota_usages_project_id_idx', 'project_id'),
sa.Index('quota_usages_user_id_idx', 'user_id'),
mysql_engine='InnoDB',
mysql_charset='utf8',
)
quotas = sa.Table('quotas', meta,
sa.Column('id', sa.Integer, primary_key=True, nullable=False),
sa.Column('created_at', sa.DateTime),
sa.Column('updated_at', sa.DateTime),
sa.Column('project_id', sa.String(length=255)),
sa.Column('resource', sa.String(length=255), nullable=False),
sa.Column('hard_limit', sa.Integer),
UniqueConstraint(
'project_id', 'resource', name='uniq_quotas0project_id0resource'),
mysql_engine='InnoDB',
mysql_charset='utf8',
)
project_user_quotas = sa.Table('project_user_quotas', meta,
sa.Column('id', sa.Integer, primary_key=True, nullable=False),
sa.Column('created_at', sa.DateTime),
sa.Column('updated_at', sa.DateTime),
sa.Column('user_id', sa.String(length=255), nullable=False),
sa.Column('project_id', sa.String(length=255), nullable=False),
sa.Column('resource', sa.String(length=255), nullable=False),
sa.Column('hard_limit', sa.Integer, nullable=True),
UniqueConstraint(
'user_id', 'project_id', 'resource',
name='uniq_project_user_quotas0user_id0project_id0resource'),
sa.Index(
'project_user_quotas_project_id_idx', 'project_id'),
sa.Index(
'project_user_quotas_user_id_idx', 'user_id'),
mysql_engine='InnoDB',
mysql_charset='utf8',
)
reservations = sa.Table('reservations', meta,
sa.Column('created_at', sa.DateTime),
sa.Column('updated_at', sa.DateTime),
sa.Column('id', sa.Integer, primary_key=True, nullable=False),
sa.Column('uuid', sa.String(length=36), nullable=False),
sa.Column(
'usage_id', sa.Integer, sa.ForeignKey('quota_usages.id'),
nullable=False),
sa.Column('project_id', sa.String(length=255)),
sa.Column('resource', sa.String(length=255)),
sa.Column('delta', sa.Integer, nullable=False),
sa.Column('expire', sa.DateTime),
sa.Column('user_id', sa.String(length=255)),
sa.Index('reservations_project_id_idx', 'project_id'),
sa.Index('reservations_uuid_idx', 'uuid'),
sa.Index('reservations_expire_idx', 'expire'),
sa.Index('reservations_user_id_idx', 'user_id'),
mysql_engine='InnoDB',
mysql_charset='utf8',
)
tables = [
cell_mappings,
host_mappings,
instance_mappings,
flavors,
flavor_extra_specs,
flavor_projects,
request_specs,
build_requests,
keypairs,
projects,
users,
resource_classes,
resource_providers,
inventories,
traits,
allocations,
consumers,
resource_provider_aggregates,
resource_provider_traits,
placement_aggregates,
aggregates,
aggregate_hosts,
aggregate_metadata,
groups,
group_policy,
group_member,
quota_classes,
quota_usages,
quotas,
project_user_quotas,
reservations,
]
for table in tables:
table.create(checkfirst=True)

View File

@ -1,22 +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,22 +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,22 +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,22 +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,22 +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,22 +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,22 +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,22 +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,22 +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,22 +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,22 +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,22 +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,22 +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,22 +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,22 +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,22 +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,22 +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,22 +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,22 +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,22 +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,4 +0,0 @@
This is a database migration repository.
More information at
https://sqlalchemy-migrate.readthedocs.io/en/latest/

View File

@ -1,20 +0,0 @@
#!/usr/bin/env python
# Copyright 2012 OpenStack Foundation
#
# 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 migrate.versioning.shell import main
if __name__ == '__main__':
main(debug='False', repository='.')

View File

@ -1,20 +0,0 @@
[db_settings]
# Used to identify which repository this database is versioned under.
# You can use the name of your project.
repository_id=nova
# The name of the database table used to track the schema version.
# This name shouldn't already be used by your project.
# If this is changed once a database is under version control, you'll need to
# change the table name in each database too.
version_table=migrate_version
# When committing a change script, Migrate will attempt to generate the
# sql for all supported databases; normally, if one of them fails - probably
# because you don't have that database installed - it is ignored and the
# commit continues, perhaps ending successfully.
# Databases in this list MUST compile successfully during a commit, or the
# entire commit will fail. List the databases your application will actually
# be using to ensure your updates to that database work properly.
# This must be a list; example: ['postgres','sqlite']
required_dbs=[]

File diff suppressed because it is too large Load Diff

View File

@ -1,22 +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,22 +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,22 +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,22 +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,22 +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,22 +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,22 +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,22 +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,22 +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,22 +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,22 +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,22 +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,22 +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,22 +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,22 +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,22 +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,22 +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,22 +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,22 +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,22 +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

@ -19,24 +19,12 @@ import os
from alembic import command as alembic_api
from alembic import config as alembic_config
from alembic.runtime import migration as alembic_migration
from migrate import exceptions as migrate_exceptions
from migrate.versioning import api as migrate_api
from migrate.versioning import repository as migrate_repository
from oslo_log import log as logging
from nova.db.api import api as api_db_api
from nova.db.main import api as main_db_api
from nova import exception
MIGRATE_INIT_VERSION = {
'main': 401,
'api': 66,
}
ALEMBIC_INIT_VERSION = {
'main': '8f2f1571d55b',
'api': 'd67eeaabee36',
}
LOG = logging.getLogger(__name__)
@ -48,16 +36,6 @@ def _get_engine(database='main', context=None):
return api_db_api.get_engine()
def _find_migrate_repo(database='main'):
"""Get the path for the migrate repository."""
path = os.path.join(
os.path.abspath(os.path.dirname(__file__)),
database, 'legacy_migrations')
return migrate_repository.Repository(path)
def _find_alembic_conf(database='main'):
"""Get the path for the alembic repository."""
@ -73,35 +51,6 @@ def _find_alembic_conf(database='main'):
return config
def _is_database_under_migrate_control(engine, repository):
try:
migrate_api.db_version(engine, repository)
return True
except migrate_exceptions.DatabaseNotControlledError:
return False
def _is_database_under_alembic_control(engine):
with engine.connect() as conn:
context = alembic_migration.MigrationContext.configure(conn)
return bool(context.get_current_revision())
def _init_alembic_on_legacy_database(engine, database, repository, config):
"""Init alembic in an existing environment with sqlalchemy-migrate."""
LOG.info(
'The database is still under sqlalchemy-migrate control; '
'applying any remaining sqlalchemy-migrate-based migrations '
'and fake applying the initial alembic migration'
)
migrate_api.upgrade(engine, repository)
# re-use the connection rather than creating a new one
with engine.begin() as connection:
config.attributes['connection'] = connection
alembic_api.stamp(config, ALEMBIC_INIT_VERSION[database])
def _upgrade_alembic(engine, config, version):
# re-use the connection rather than creating a new one
with engine.begin() as connection:
@ -126,7 +75,6 @@ def db_sync(version=None, database='main', context=None):
engine = _get_engine(database, context=context)
repository = _find_migrate_repo(database)
config = _find_alembic_conf(database)
# discard the URL stored in alembic.ini in favour of the URL configured
# for the engine, casting from 'sqlalchemy.engine.url.URL' to str in the
@ -138,16 +86,6 @@ def db_sync(version=None, database='main', context=None):
url = str(engine.url).replace('%', '%%')
config.set_main_option('sqlalchemy.url', url)
# if we're in a deployment where sqlalchemy-migrate is already present,
# then apply all the updates for that and fake apply the initial alembic
# migration; if we're not then 'upgrade' will take care of everything
# this should be a one-time operation
if (
_is_database_under_migrate_control(engine, repository) and
not _is_database_under_alembic_control(engine)
):
_init_alembic_on_legacy_database(engine, database, repository, config)
# apply anything later
LOG.info('Applying migration(s)')
@ -161,17 +99,10 @@ def db_version(database='main', context=None):
if database not in ('main', 'api'):
raise exception.Invalid('%s is not a valid database' % database)
repository = _find_migrate_repo(database)
engine = _get_engine(database, context=context)
migrate_version = None
if _is_database_under_migrate_control(engine, repository):
migrate_version = migrate_api.db_version(engine, repository)
with engine.connect() as conn:
m_context = alembic_migration.MigrationContext.configure(conn)
version = m_context.get_current_revision()
alembic_version = None
if _is_database_under_alembic_control(engine):
with engine.connect() as conn:
m_context = alembic_migration.MigrationContext.configure(conn)
alembic_version = m_context.get_current_revision()
return alembic_version or migrate_version
return version

View File

@ -25,7 +25,6 @@ from unittest import mock
from alembic import command as alembic_api
from alembic import script as alembic_script
from migrate.versioning import api as migrate_api
from oslo_db.sqlalchemy import enginefacade
from oslo_db.sqlalchemy import test_fixtures
from oslo_db.sqlalchemy import test_migrations
@ -127,47 +126,6 @@ class TestModelsSyncPostgreSQL(
FIXTURE = test_fixtures.PostgresqlOpportunisticFixture
class NovaModelsMigrationsLegacySync(NovaModelsMigrationsSync):
"""Test that the models match the database after old migrations are run."""
def db_sync(self, engine):
# the 'nova.db.migration.db_sync' method will not use the legacy
# sqlalchemy-migrate-based migration flow unless the database is
# already controlled with sqlalchemy-migrate, so we need to manually
# enable version controlling with this tool to test this code path
repository = migration._find_migrate_repo(database='api')
migrate_api.version_control(
engine, repository, migration.MIGRATE_INIT_VERSION['api'])
# now we can apply migrations as expected and the legacy path will be
# followed
super().db_sync(engine)
class TestModelsLegacySyncSQLite(
NovaModelsMigrationsLegacySync,
test_fixtures.OpportunisticDBTestMixin,
testtools.TestCase,
):
pass
class TestModelsLegacySyncMySQL(
NovaModelsMigrationsLegacySync,
test_fixtures.OpportunisticDBTestMixin,
testtools.TestCase,
):
FIXTURE = test_fixtures.MySQLOpportunisticFixture
class TestModelsLegacySyncPostgreSQL(
NovaModelsMigrationsLegacySync,
test_fixtures.OpportunisticDBTestMixin,
testtools.TestCase,
):
FIXTURE = test_fixtures.PostgresqlOpportunisticFixture
class NovaMigrationsWalk(
test_fixtures.OpportunisticDBTestMixin, test.NoDBTestCase,
):
@ -180,7 +138,7 @@ class NovaMigrationsWalk(
super().setUp()
self.engine = enginefacade.writer.get_engine()
self.config = migration._find_alembic_conf('api')
self.init_version = migration.ALEMBIC_INIT_VERSION['api']
self.init_version = 'd67eeaabee36'
def _migrate_up(self, connection, revision):
if revision == self.init_version: # no tests for the initial revision

View File

@ -30,7 +30,6 @@ from unittest import mock
from alembic import command as alembic_api
from alembic import script as alembic_script
import fixtures
from migrate.versioning import api as migrate_api
from oslo_db.sqlalchemy import enginefacade
from oslo_db.sqlalchemy import test_fixtures
from oslo_db.sqlalchemy import test_migrations
@ -174,47 +173,6 @@ class TestModelsSyncPostgreSQL(
FIXTURE = test_fixtures.PostgresqlOpportunisticFixture
class NovaModelsMigrationsLegacySync(NovaModelsMigrationsSync):
"""Test that the models match the database after old migrations are run."""
def db_sync(self, engine):
# the 'nova.db.migration.db_sync' method will not use the legacy
# sqlalchemy-migrate-based migration flow unless the database is
# already controlled with sqlalchemy-migrate, so we need to manually
# enable version controlling with this tool to test this code path
repository = migration._find_migrate_repo(database='main')
migrate_api.version_control(
engine, repository, migration.MIGRATE_INIT_VERSION['main'])
# now we can apply migrations as expected and the legacy path will be
# followed
super().db_sync(engine)
class TestModelsLegacySyncSQLite(
NovaModelsMigrationsLegacySync,
test_fixtures.OpportunisticDBTestMixin,
base.BaseTestCase,
):
pass
class TestModelsLegacySyncMySQL(
NovaModelsMigrationsLegacySync,
test_fixtures.OpportunisticDBTestMixin,
base.BaseTestCase,
):
FIXTURE = test_fixtures.MySQLOpportunisticFixture
class TestModelsLegacySyncPostgreSQL(
NovaModelsMigrationsLegacySync,
test_fixtures.OpportunisticDBTestMixin,
base.BaseTestCase,
):
FIXTURE = test_fixtures.PostgresqlOpportunisticFixture
class NovaMigrationsWalk(
test_fixtures.OpportunisticDBTestMixin, test.NoDBTestCase,
):
@ -227,7 +185,7 @@ class NovaMigrationsWalk(
super().setUp()
self.engine = enginefacade.writer.get_engine()
self.config = migration._find_alembic_conf('main')
self.init_version = migration.ALEMBIC_INIT_VERSION['main']
self.init_version = '8f2f1571d55b'
def assertIndexExists(self, connection, table_name, index):
self.assertTrue(

View File

@ -12,14 +12,10 @@
# License for the specific language governing permissions and limitations
# under the License.
import glob
import os
from unittest import mock
import urllib
from alembic.runtime import migration as alembic_migration
from migrate import exceptions as migrate_exceptions
from migrate.versioning import api as migrate_api
from nova.db.api import api as api_db_api
from nova.db.main import api as main_db_api
@ -68,17 +64,9 @@ class TestDBSync(test.NoDBTestCase):
migration.db_sync, '402')
@mock.patch.object(migration, '_upgrade_alembic')
@mock.patch.object(migration, '_init_alembic_on_legacy_database')
@mock.patch.object(migration, '_is_database_under_alembic_control')
@mock.patch.object(migration, '_is_database_under_migrate_control')
@mock.patch.object(migration, '_find_alembic_conf')
@mock.patch.object(migration, '_find_migrate_repo')
@mock.patch.object(migration, '_get_engine')
def _test_db_sync(
self, has_migrate, has_alembic, mock_get_engine, mock_find_repo,
mock_find_conf, mock_is_migrate, mock_is_alembic, mock_init,
mock_upgrade,
):
def test_db_sync(self, mock_get_engine, mock_find_conf, mock_upgrade):
# return an encoded URL to mimic sqlalchemy
mock_get_engine.return_value.url = (
@ -86,13 +74,10 @@ class TestDBSync(test.NoDBTestCase):
'read_default_file=%2Fetc%2Fmy.cnf.d%2Fnova.cnf'
'&read_default_group=nova'
)
mock_is_migrate.return_value = has_migrate
mock_is_alembic.return_value = has_alembic
migration.db_sync()
mock_get_engine.assert_called_once_with('main', context=None)
mock_find_repo.assert_called_once_with('main')
mock_find_conf.assert_called_once_with('main')
mock_find_conf.return_value.set_main_option.assert_called_once_with(
'sqlalchemy.url',
@ -100,93 +85,25 @@ class TestDBSync(test.NoDBTestCase):
'read_default_file=%%2Fetc%%2Fmy.cnf.d%%2Fnova.cnf' # ...
'&read_default_group=nova'
)
mock_is_migrate.assert_called_once_with(
mock_get_engine.return_value, mock_find_repo.return_value)
if has_migrate:
mock_is_alembic.assert_called_once_with(
mock_get_engine.return_value)
else:
mock_is_alembic.assert_not_called()
# we should only attempt the upgrade of the remaining
# sqlalchemy-migrate-based migrations and fake apply of the initial
# alembic migrations if sqlalchemy-migrate is in place but alembic
# hasn't been used yet
if has_migrate and not has_alembic:
mock_init.assert_called_once_with(
mock_get_engine.return_value, 'main',
mock_find_repo.return_value, mock_find_conf.return_value)
else:
mock_init.assert_not_called()
# however, we should always attempt to upgrade the requested migration
# to alembic
mock_upgrade.assert_called_once_with(
mock_get_engine.return_value, mock_find_conf.return_value, None)
def test_db_sync_new_deployment(self):
"""Mimic a new deployment without existing sqlalchemy-migrate cruft."""
has_migrate = False
has_alembic = False
self._test_db_sync(has_migrate, has_alembic)
def test_db_sync_with_existing_migrate_database(self):
"""Mimic a deployment currently managed by sqlalchemy-migrate."""
has_migrate = True
has_alembic = False
self._test_db_sync(has_migrate, has_alembic)
def test_db_sync_with_existing_alembic_database(self):
"""Mimic a deployment that's already switched to alembic."""
has_migrate = True
has_alembic = True
self._test_db_sync(has_migrate, has_alembic)
mock_get_engine.return_value, mock_find_conf.return_value, None,
)
@mock.patch.object(alembic_migration.MigrationContext, 'configure')
@mock.patch.object(migrate_api, 'db_version')
@mock.patch.object(migration, '_is_database_under_alembic_control')
@mock.patch.object(migration, '_is_database_under_migrate_control')
@mock.patch.object(migration, '_get_engine')
@mock.patch.object(migration, '_find_migrate_repo')
class TestDBVersion(test.NoDBTestCase):
def test_db_version_invalid_database(
self, mock_find_repo, mock_get_engine, mock_is_migrate,
mock_is_alembic, mock_migrate_version, mock_m_context_configure,
self, mock_get_engine, mock_m_context_configure,
):
"""We only have two databases."""
self.assertRaises(
exception.Invalid, migration.db_version, database='invalid')
def test_db_version_migrate(
self, mock_find_repo, mock_get_engine, mock_is_migrate,
mock_is_alembic, mock_migrate_version, mock_m_context_configure,
):
"""Database is controlled by sqlalchemy-migrate."""
mock_is_migrate.return_value = True
mock_is_alembic.return_value = False
ret = migration.db_version('main')
self.assertEqual(mock_migrate_version.return_value, ret)
mock_find_repo.assert_called_once_with('main')
mock_get_engine.assert_called_once_with('main', context=None)
mock_is_migrate.assert_called_once()
mock_is_alembic.assert_called_once()
mock_migrate_version.assert_called_once_with(
mock_get_engine.return_value, mock_find_repo.return_value)
mock_m_context_configure.assert_not_called()
def test_db_version_alembic(
self, mock_find_repo, mock_get_engine, mock_is_migrate,
mock_is_alembic, mock_migrate_version, mock_m_context_configure,
):
def test_db_version(self, mock_get_engine, mock_m_context_configure):
"""Database is controlled by alembic."""
mock_is_migrate.return_value = False
mock_is_alembic.return_value = True
ret = migration.db_version('main')
mock_m_context = mock_m_context_configure.return_value
self.assertEqual(
@ -194,31 +111,9 @@ class TestDBVersion(test.NoDBTestCase):
ret
)
mock_find_repo.assert_called_once_with('main')
mock_get_engine.assert_called_once_with('main', context=None)
mock_is_migrate.assert_called_once()
mock_is_alembic.assert_called_once()
mock_migrate_version.assert_not_called()
mock_m_context_configure.assert_called_once()
def test_db_version_not_controlled(
self, mock_find_repo, mock_get_engine, mock_is_migrate,
mock_is_alembic, mock_migrate_version, mock_m_context_configure,
):
"""Database is not controlled."""
mock_is_migrate.return_value = False
mock_is_alembic.return_value = False
ret = migration.db_version()
self.assertIsNone(ret)
mock_find_repo.assert_called_once_with('main')
mock_get_engine.assert_called_once_with('main', context=None)
mock_is_migrate.assert_called_once()
mock_is_alembic.assert_called_once()
mock_migrate_version.assert_not_called()
mock_m_context_configure.assert_not_called()
class TestGetEngine(test.NoDBTestCase):
@ -237,77 +132,3 @@ class TestGetEngine(test.NoDBTestCase):
engine = migration._get_engine('api')
self.assertEqual('engine', engine)
mock_get_engine.assert_called_once_with()
class TestDatabaseUnderVersionControl(test.NoDBTestCase):
@mock.patch.object(migrate_api, 'db_version')
def test__is_database_under_migrate_control__true(self, mock_db_version):
ret = migration._is_database_under_migrate_control('engine', 'repo')
self.assertTrue(ret)
mock_db_version.assert_called_once_with('engine', 'repo')
@mock.patch.object(migrate_api, 'db_version')
def test__is_database_under_migrate_control__false(self, mock_db_version):
mock_db_version.side_effect = \
migrate_exceptions.DatabaseNotControlledError()
ret = migration._is_database_under_migrate_control('engine', 'repo')
self.assertFalse(ret)
mock_db_version.assert_called_once_with('engine', 'repo')
@mock.patch.object(alembic_migration.MigrationContext, 'configure')
def test__is_database_under_alembic_control__true(self, mock_configure):
context = mock_configure.return_value
context.get_current_revision.return_value = 'foo'
engine = mock.MagicMock()
ret = migration._is_database_under_alembic_control(engine)
self.assertTrue(ret)
context.get_current_revision.assert_called_once_with()
@mock.patch.object(alembic_migration.MigrationContext, 'configure')
def test__is_database_under_alembic_control__false(self, mock_configure):
context = mock_configure.return_value
context.get_current_revision.return_value = None
engine = mock.MagicMock()
ret = migration._is_database_under_alembic_control(engine)
self.assertFalse(ret)
context.get_current_revision.assert_called_once_with()
class ProjectTestCase(test.NoDBTestCase):
def test_no_migrations_have_downgrade(self):
topdir = os.path.normpath(os.path.dirname(__file__) + '/../../../')
# Walk both the nova_api and nova (cell) database migrations.
includes_downgrade = []
for directory in (
os.path.join(topdir, 'db', 'main', 'legacy_migrations'),
os.path.join(topdir, 'db', 'api', 'legacy_migrations'),
):
py_glob = os.path.join(directory, 'versions', '*.py')
for path in glob.iglob(py_glob):
has_upgrade = False
has_downgrade = False
with open(path, "r") as f:
for line in f:
if 'def upgrade(' in line:
has_upgrade = True
if 'def downgrade(' in line:
has_downgrade = True
if has_upgrade and has_downgrade:
fname = os.path.basename(path)
includes_downgrade.append(fname)
helpful_msg = (
"The following migrations have a downgrade "
"which is not supported:"
"\n\t%s" % '\n\t'.join(sorted(includes_downgrade)))
self.assertFalse(includes_downgrade, helpful_msg)

View File

@ -0,0 +1,5 @@
---
upgrade:
- |
The legacy ``sqlalchemy-migrate`` migrations, which have been deprecated
since Wallaby, have been removed. There should be no end-user impact.

View File

@ -16,7 +16,6 @@ greenlet>=0.4.15 # MIT
PasteDeploy>=1.5.0 # MIT
Paste>=2.0.2 # MIT
PrettyTable>=0.7.1 # BSD
sqlalchemy-migrate>=0.13.0 # Apache-2.0
alembic>=1.5.0 # MIT
netaddr>=0.7.18 # BSD
netifaces>=0.10.4 # MIT