Merge "db: Remove legacy migrations"

This commit is contained in:
Zuul
2023-04-17 01:08:26 +00:00
committed by Gerrit Code Review
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 The database migration engine was changed from ``sqlalchemy-migrate`` to
``alembic``. ``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 The `alembic`__ database migration tool is used to manage schema migrations in
nova. The migration files and related metadata can be found in nova. The migration files and related metadata can be found in
``nova/db/api/migrations`` (for the API database) and ``nova/db/api/migrations`` (for the API database) and
@@ -36,10 +40,10 @@ respectively.
.. note:: .. note::
There are also legacy migrations provided in the ``legacy_migrations`` There were also legacy migrations provided in the ``legacy_migrations``
subdirectory for both the API and main databases. These are provided to subdirectory for both the API and main databases. These were provided to
facilitate upgrades from pre-Xena (24.0.0) deployments and will be removed facilitate upgrades from pre-Xena (24.0.0) deployments. They were removed
in a future release. They should not be modified or extended. in the 27.0.0 (Antelope) release.
The best reference for alembic is the `alembic documentation`__, but a small The best reference for alembic is the `alembic documentation`__, but a small
example is provided here. You can create the migration either manually or 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 command as alembic_api
from alembic import config as alembic_config from alembic import config as alembic_config
from alembic.runtime import migration as alembic_migration 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 oslo_log import log as logging
from nova.db.api import api as api_db_api from nova.db.api import api as api_db_api
from nova.db.main import api as main_db_api from nova.db.main import api as main_db_api
from nova import exception from nova import exception
MIGRATE_INIT_VERSION = {
'main': 401,
'api': 66,
}
ALEMBIC_INIT_VERSION = {
'main': '8f2f1571d55b',
'api': 'd67eeaabee36',
}
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
@@ -48,16 +36,6 @@ def _get_engine(database='main', context=None):
return api_db_api.get_engine() 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'): def _find_alembic_conf(database='main'):
"""Get the path for the alembic repository.""" """Get the path for the alembic repository."""
@@ -73,35 +51,6 @@ def _find_alembic_conf(database='main'):
return config 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): def _upgrade_alembic(engine, config, version):
# re-use the connection rather than creating a new one # re-use the connection rather than creating a new one
with engine.begin() as connection: with engine.begin() as connection:
@@ -126,7 +75,6 @@ def db_sync(version=None, database='main', context=None):
engine = _get_engine(database, context=context) engine = _get_engine(database, context=context)
repository = _find_migrate_repo(database)
config = _find_alembic_conf(database) config = _find_alembic_conf(database)
# discard the URL stored in alembic.ini in favour of the URL configured # 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 # 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('%', '%%') url = str(engine.url).replace('%', '%%')
config.set_main_option('sqlalchemy.url', url) 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 # apply anything later
LOG.info('Applying migration(s)') LOG.info('Applying migration(s)')
@@ -161,17 +99,10 @@ def db_version(database='main', context=None):
if database not in ('main', 'api'): if database not in ('main', 'api'):
raise exception.Invalid('%s is not a valid database' % database) raise exception.Invalid('%s is not a valid database' % database)
repository = _find_migrate_repo(database)
engine = _get_engine(database, context=context) engine = _get_engine(database, context=context)
migrate_version = None with engine.connect() as conn:
if _is_database_under_migrate_control(engine, repository): m_context = alembic_migration.MigrationContext.configure(conn)
migrate_version = migrate_api.db_version(engine, repository) version = m_context.get_current_revision()
alembic_version = None return version
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

View File

@@ -25,7 +25,6 @@ from unittest import mock
from alembic import command as alembic_api from alembic import command as alembic_api
from alembic import script as alembic_script 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 enginefacade
from oslo_db.sqlalchemy import test_fixtures from oslo_db.sqlalchemy import test_fixtures
from oslo_db.sqlalchemy import test_migrations from oslo_db.sqlalchemy import test_migrations
@@ -127,47 +126,6 @@ class TestModelsSyncPostgreSQL(
FIXTURE = test_fixtures.PostgresqlOpportunisticFixture 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( class NovaMigrationsWalk(
test_fixtures.OpportunisticDBTestMixin, test.NoDBTestCase, test_fixtures.OpportunisticDBTestMixin, test.NoDBTestCase,
): ):
@@ -180,7 +138,7 @@ class NovaMigrationsWalk(
super().setUp() super().setUp()
self.engine = enginefacade.writer.get_engine() self.engine = enginefacade.writer.get_engine()
self.config = migration._find_alembic_conf('api') 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): def _migrate_up(self, connection, revision):
if revision == self.init_version: # no tests for the initial 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 command as alembic_api
from alembic import script as alembic_script from alembic import script as alembic_script
import fixtures import fixtures
from migrate.versioning import api as migrate_api
from oslo_db.sqlalchemy import enginefacade from oslo_db.sqlalchemy import enginefacade
from oslo_db.sqlalchemy import test_fixtures from oslo_db.sqlalchemy import test_fixtures
from oslo_db.sqlalchemy import test_migrations from oslo_db.sqlalchemy import test_migrations
@@ -174,47 +173,6 @@ class TestModelsSyncPostgreSQL(
FIXTURE = test_fixtures.PostgresqlOpportunisticFixture 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( class NovaMigrationsWalk(
test_fixtures.OpportunisticDBTestMixin, test.NoDBTestCase, test_fixtures.OpportunisticDBTestMixin, test.NoDBTestCase,
): ):
@@ -227,7 +185,7 @@ class NovaMigrationsWalk(
super().setUp() super().setUp()
self.engine = enginefacade.writer.get_engine() self.engine = enginefacade.writer.get_engine()
self.config = migration._find_alembic_conf('main') 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): def assertIndexExists(self, connection, table_name, index):
self.assertTrue( self.assertTrue(

View File

@@ -12,14 +12,10 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import glob
import os
from unittest import mock from unittest import mock
import urllib import urllib
from alembic.runtime import migration as alembic_migration 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.api import api as api_db_api
from nova.db.main import api as main_db_api from nova.db.main import api as main_db_api
@@ -68,17 +64,9 @@ class TestDBSync(test.NoDBTestCase):
migration.db_sync, '402') migration.db_sync, '402')
@mock.patch.object(migration, '_upgrade_alembic') @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_alembic_conf')
@mock.patch.object(migration, '_find_migrate_repo')
@mock.patch.object(migration, '_get_engine') @mock.patch.object(migration, '_get_engine')
def _test_db_sync( def test_db_sync(self, mock_get_engine, mock_find_conf, mock_upgrade):
self, has_migrate, has_alembic, mock_get_engine, mock_find_repo,
mock_find_conf, mock_is_migrate, mock_is_alembic, mock_init,
mock_upgrade,
):
# return an encoded URL to mimic sqlalchemy # return an encoded URL to mimic sqlalchemy
mock_get_engine.return_value.url = ( 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_file=%2Fetc%2Fmy.cnf.d%2Fnova.cnf'
'&read_default_group=nova' '&read_default_group=nova'
) )
mock_is_migrate.return_value = has_migrate
mock_is_alembic.return_value = has_alembic
migration.db_sync() migration.db_sync()
mock_get_engine.assert_called_once_with('main', context=None) 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.assert_called_once_with('main')
mock_find_conf.return_value.set_main_option.assert_called_once_with( mock_find_conf.return_value.set_main_option.assert_called_once_with(
'sqlalchemy.url', 'sqlalchemy.url',
@@ -100,93 +85,25 @@ class TestDBSync(test.NoDBTestCase):
'read_default_file=%%2Fetc%%2Fmy.cnf.d%%2Fnova.cnf' # ... 'read_default_file=%%2Fetc%%2Fmy.cnf.d%%2Fnova.cnf' # ...
'&read_default_group=nova' '&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_upgrade.assert_called_once_with(
mock_get_engine.return_value, mock_find_conf.return_value, None) 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.patch.object(alembic_migration.MigrationContext, 'configure') @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, '_get_engine')
@mock.patch.object(migration, '_find_migrate_repo')
class TestDBVersion(test.NoDBTestCase): class TestDBVersion(test.NoDBTestCase):
def test_db_version_invalid_database( def test_db_version_invalid_database(
self, mock_find_repo, mock_get_engine, mock_is_migrate, self, mock_get_engine, mock_m_context_configure,
mock_is_alembic, mock_migrate_version, mock_m_context_configure,
): ):
"""We only have two databases.""" """We only have two databases."""
self.assertRaises( self.assertRaises(
exception.Invalid, migration.db_version, database='invalid') exception.Invalid, migration.db_version, database='invalid')
def test_db_version_migrate( def test_db_version(self, mock_get_engine, mock_m_context_configure):
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,
):
"""Database is controlled by alembic.""" """Database is controlled by alembic."""
mock_is_migrate.return_value = False
mock_is_alembic.return_value = True
ret = migration.db_version('main') ret = migration.db_version('main')
mock_m_context = mock_m_context_configure.return_value mock_m_context = mock_m_context_configure.return_value
self.assertEqual( self.assertEqual(
@@ -194,31 +111,9 @@ class TestDBVersion(test.NoDBTestCase):
ret ret
) )
mock_find_repo.assert_called_once_with('main')
mock_get_engine.assert_called_once_with('main', context=None) 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() 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): class TestGetEngine(test.NoDBTestCase):
@@ -237,77 +132,3 @@ class TestGetEngine(test.NoDBTestCase):
engine = migration._get_engine('api') engine = migration._get_engine('api')
self.assertEqual('engine', engine) self.assertEqual('engine', engine)
mock_get_engine.assert_called_once_with() 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 PasteDeploy>=1.5.0 # MIT
Paste>=2.0.2 # MIT Paste>=2.0.2 # MIT
PrettyTable>=0.7.1 # BSD PrettyTable>=0.7.1 # BSD
sqlalchemy-migrate>=0.13.0 # Apache-2.0
alembic>=1.5.0 # MIT alembic>=1.5.0 # MIT
netaddr>=0.7.18 # BSD netaddr>=0.7.18 # BSD
netifaces>=0.10.4 # MIT netifaces>=0.10.4 # MIT