apidb: Compact Mitaka database migrations

Specific changes include:

- Add 'request_specs' table (004)
- Add 'flavors', 'flavor_extra_specs' and 'flavor_projects' tables (005)
- Add 'build_requests' table (006)
- Alter 'cell_id' column of 'instance_mappings' table to be nullable
  (007)

Change-Id: I1b6be3eb61f3e21da69a42ea32a19ce373b0a898
Signed-off-by: Stephen Finucane <stephenfin@redhat.com>
This commit is contained in:
Stephen Finucane 2020-10-22 15:25:30 +01:00
parent d97fd31131
commit d2449232bd
8 changed files with 192 additions and 379 deletions

View File

@ -1,81 +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
from sqlalchemy import Column
from sqlalchemy import DateTime
from sqlalchemy import Index
from sqlalchemy import Integer
from sqlalchemy import MetaData
from sqlalchemy import String
from sqlalchemy import Table
from sqlalchemy import Text
def upgrade(migrate_engine):
meta = MetaData()
meta.bind = migrate_engine
cell_mappings = Table('cell_mappings', meta,
Column('created_at', DateTime),
Column('updated_at', DateTime),
Column('id', Integer, primary_key=True, nullable=False),
Column('uuid', String(length=36), nullable=False),
Column('name', String(length=255)),
Column('transport_url', Text()),
Column('database_connection', Text()),
UniqueConstraint('uuid', name='uniq_cell_mappings0uuid'),
Index('uuid_idx', 'uuid'),
mysql_engine='InnoDB',
mysql_charset='utf8'
)
host_mappings = Table('host_mappings', meta,
Column('created_at', DateTime),
Column('updated_at', DateTime),
Column('id', Integer, primary_key=True, nullable=False),
Column('cell_id', Integer, nullable=False),
Column('host', String(length=255), nullable=False),
UniqueConstraint(
'host', name='uniq_host_mappings0host'),
Index('host_idx', 'host'),
ForeignKeyConstraint(
columns=['cell_id'], refcolumns=[cell_mappings.c.id]),
mysql_engine='InnoDB',
mysql_charset='utf8'
)
instance_mappings = Table('instance_mappings', meta,
Column('created_at', DateTime),
Column('updated_at', DateTime),
Column('id', Integer, primary_key=True, nullable=False),
Column('instance_uuid', String(length=36), nullable=False),
Column('cell_id', Integer, nullable=False),
Column('project_id', String(length=255), nullable=False),
UniqueConstraint(
'instance_uuid', name='uniq_instance_mappings0instance_uuid'),
Index('instance_uuid_idx', 'instance_uuid'),
Index('project_id_idx', 'project_id'),
ForeignKeyConstraint(
columns=['cell_id'], refcolumns=[cell_mappings.c.id]),
mysql_engine='InnoDB',
mysql_charset='utf8'
)
tables = [
cell_mappings,
host_mappings,
instance_mappings,
]
for table in tables:
table.create(checkfirst=True)

View File

@ -1,41 +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 import UniqueConstraint
from sqlalchemy import Column
from sqlalchemy import DateTime
from sqlalchemy import Index
from sqlalchemy import Integer
from sqlalchemy import MetaData
from sqlalchemy import String
from sqlalchemy import Table
from sqlalchemy import Text
def upgrade(migrate_engine):
meta = MetaData()
meta.bind = migrate_engine
request_specs = Table('request_specs', meta,
Column('created_at', DateTime),
Column('updated_at', DateTime),
Column('id', Integer, primary_key=True, nullable=False),
Column('instance_uuid', String(36), nullable=False),
Column('spec', Text, nullable=False),
UniqueConstraint('instance_uuid',
name='uniq_request_specs0instance_uuid'),
Index('request_spec_instance_uuid_idx', 'instance_uuid'),
mysql_engine='InnoDB',
mysql_charset='utf8'
)
request_specs.create(checkfirst=True)

View File

@ -1,82 +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
from sqlalchemy import Boolean
from sqlalchemy import Column
from sqlalchemy import DateTime
from sqlalchemy import Float
from sqlalchemy import Index
from sqlalchemy import Integer
from sqlalchemy import MetaData
from sqlalchemy import String
from sqlalchemy import Table
def upgrade(migrate_engine):
meta = MetaData()
meta.bind = migrate_engine
flavors = Table('flavors', meta,
Column('created_at', DateTime),
Column('updated_at', DateTime),
Column('name', String(length=255), nullable=False),
Column('id', Integer, primary_key=True, nullable=False),
Column('memory_mb', Integer, nullable=False),
Column('vcpus', Integer, nullable=False),
Column('swap', Integer, nullable=False),
Column('vcpu_weight', Integer),
Column('flavorid', String(length=255), nullable=False),
Column('rxtx_factor', Float),
Column('root_gb', Integer),
Column('ephemeral_gb', Integer),
Column('disabled', Boolean),
Column('is_public', Boolean),
UniqueConstraint("flavorid", name="uniq_flavors0flavorid"),
UniqueConstraint("name", name="uniq_flavors0name"),
mysql_engine='InnoDB',
mysql_charset='utf8'
)
flavors.create(checkfirst=True)
flavor_extra_specs = Table('flavor_extra_specs', meta,
Column('created_at', DateTime),
Column('updated_at', DateTime),
Column('id', Integer, primary_key=True, nullable=False),
Column('flavor_id', Integer, nullable=False),
Column('key', String(length=255), nullable=False),
Column('value', String(length=255)),
UniqueConstraint('flavor_id', 'key',
name='uniq_flavor_extra_specs0flavor_id0key'),
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_extra_specs.create(checkfirst=True)
flavor_projects = Table('flavor_projects', meta,
Column('created_at', DateTime),
Column('updated_at', DateTime),
Column('id', Integer, primary_key=True, nullable=False),
Column('flavor_id', Integer, nullable=False),
Column('project_id', 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'
)
flavor_projects.create(checkfirst=True)

View File

@ -1,68 +0,0 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from migrate.changeset.constraint import ForeignKeyConstraint
from migrate import UniqueConstraint
from sqlalchemy import Boolean
from sqlalchemy import Column
from sqlalchemy import DateTime
from sqlalchemy import dialects
from sqlalchemy import Enum
from sqlalchemy import Index
from sqlalchemy import Integer
from sqlalchemy import MetaData
from sqlalchemy import String
from sqlalchemy import Table
from sqlalchemy import Text
def InetSmall():
return String(length=39).with_variant(dialects.postgresql.INET(),
'postgresql')
def upgrade(migrate_engine):
meta = MetaData()
meta.bind = migrate_engine
request_specs = Table('request_specs', meta, autoload=True)
build_requests = Table('build_requests', meta,
Column('created_at', DateTime),
Column('updated_at', DateTime),
Column('id', Integer, primary_key=True, nullable=False),
Column('request_spec_id', Integer, nullable=False),
Column('project_id', String(length=255), nullable=False),
Column('user_id', String(length=255), nullable=False),
Column('display_name', String(length=255)),
Column('instance_metadata', Text),
Column('progress', Integer),
Column('vm_state', String(length=255)),
Column('task_state', String(length=255)),
Column('image_ref', String(length=255)),
Column('access_ip_v4', InetSmall()),
Column('access_ip_v6', InetSmall()),
Column('info_cache', Text),
Column('security_groups', Text, nullable=False),
Column('config_drive', Boolean, default=False, nullable=False),
Column('key_name', String(length=255)),
Column('locked_by', Enum('owner', 'admin',
name='build_requests0locked_by')),
UniqueConstraint('request_spec_id',
name='uniq_build_requests0request_spec_id'),
Index('build_requests_project_id_idx', 'project_id'),
ForeignKeyConstraint(columns=['request_spec_id'],
refcolumns=[request_specs.c.id]),
mysql_engine='InnoDB',
mysql_charset='utf8'
)
build_requests.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.
from sqlalchemy import MetaData
from sqlalchemy import Table
def upgrade(migrate_engine):
meta = MetaData()
meta.bind = migrate_engine
instance_mapping = Table('instance_mappings', meta, autoload=True)
instance_mapping.c.cell_id.alter(nullable=True)

View File

@ -0,0 +1,191 @@
# 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
from sqlalchemy import Boolean
from sqlalchemy import Column
from sqlalchemy import DateTime
from sqlalchemy import dialects
from sqlalchemy import Enum
from sqlalchemy import Float
from sqlalchemy import Index
from sqlalchemy import Integer
from sqlalchemy import MetaData
from sqlalchemy import String
from sqlalchemy import Table
from sqlalchemy import Text
def InetSmall():
return String(length=39).with_variant(
dialects.postgresql.INET(), 'postgresql'
)
def upgrade(migrate_engine):
meta = MetaData()
meta.bind = migrate_engine
cell_mappings = Table('cell_mappings', meta,
Column('created_at', DateTime),
Column('updated_at', DateTime),
Column('id', Integer, primary_key=True, nullable=False),
Column('uuid', String(length=36), nullable=False),
Column('name', String(length=255)),
Column('transport_url', Text()),
Column('database_connection', Text()),
UniqueConstraint('uuid', name='uniq_cell_mappings0uuid'),
Index('uuid_idx', 'uuid'),
mysql_engine='InnoDB',
mysql_charset='utf8'
)
host_mappings = Table('host_mappings', meta,
Column('created_at', DateTime),
Column('updated_at', DateTime),
Column('id', Integer, primary_key=True, nullable=False),
Column('cell_id', Integer, nullable=False),
Column('host', String(length=255), nullable=False),
UniqueConstraint(
'host', name='uniq_host_mappings0host'),
Index('host_idx', 'host'),
ForeignKeyConstraint(
columns=['cell_id'], refcolumns=[cell_mappings.c.id]),
mysql_engine='InnoDB',
mysql_charset='utf8'
)
instance_mappings = Table('instance_mappings', meta,
Column('created_at', DateTime),
Column('updated_at', DateTime),
Column('id', Integer, primary_key=True, nullable=False),
Column('instance_uuid', String(length=36), nullable=False),
Column('cell_id', Integer, nullable=True),
Column('project_id', String(length=255), nullable=False),
UniqueConstraint(
'instance_uuid', name='uniq_instance_mappings0instance_uuid'),
Index('instance_uuid_idx', 'instance_uuid'),
Index('project_id_idx', 'project_id'),
ForeignKeyConstraint(
columns=['cell_id'], refcolumns=[cell_mappings.c.id]),
mysql_engine='InnoDB',
mysql_charset='utf8'
)
flavors = Table('flavors', meta,
Column('created_at', DateTime),
Column('updated_at', DateTime),
Column('name', String(length=255), nullable=False),
Column('id', Integer, primary_key=True, nullable=False),
Column('memory_mb', Integer, nullable=False),
Column('vcpus', Integer, nullable=False),
Column('swap', Integer, nullable=False),
Column('vcpu_weight', Integer),
Column('flavorid', String(length=255), nullable=False),
Column('rxtx_factor', Float),
Column('root_gb', Integer),
Column('ephemeral_gb', Integer),
Column('disabled', Boolean),
Column('is_public', Boolean),
UniqueConstraint('flavorid', name='uniq_flavors0flavorid'),
UniqueConstraint('name', name='uniq_flavors0name'),
mysql_engine='InnoDB',
mysql_charset='utf8'
)
flavor_extra_specs = Table('flavor_extra_specs', meta,
Column('created_at', DateTime),
Column('updated_at', DateTime),
Column('id', Integer, primary_key=True, nullable=False),
Column('flavor_id', Integer, nullable=False),
Column('key', String(length=255), nullable=False),
Column('value', String(length=255)),
UniqueConstraint(
'flavor_id', 'key', name='uniq_flavor_extra_specs0flavor_id0key'),
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 = Table('flavor_projects', meta,
Column('created_at', DateTime),
Column('updated_at', DateTime),
Column('id', Integer, primary_key=True, nullable=False),
Column('flavor_id', Integer, nullable=False),
Column('project_id', 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 = Table('request_specs', meta,
Column('created_at', DateTime),
Column('updated_at', DateTime),
Column('id', Integer, primary_key=True, nullable=False),
Column('instance_uuid', String(36), nullable=False),
Column('spec', Text, nullable=False),
UniqueConstraint(
'instance_uuid', name='uniq_request_specs0instance_uuid'),
Index('request_spec_instance_uuid_idx', 'instance_uuid'),
mysql_engine='InnoDB',
mysql_charset='utf8'
)
build_requests = Table('build_requests', meta,
Column('created_at', DateTime),
Column('updated_at', DateTime),
Column('id', Integer, primary_key=True, nullable=False),
Column('request_spec_id', Integer, nullable=False),
Column('project_id', String(length=255), nullable=False),
Column('user_id', String(length=255), nullable=False),
Column('display_name', String(length=255)),
Column('instance_metadata', Text),
Column('progress', Integer),
Column('vm_state', String(length=255)),
Column('task_state', String(length=255)),
Column('image_ref', String(length=255)),
Column('access_ip_v4', InetSmall()),
Column('access_ip_v6', InetSmall()),
Column('info_cache', Text),
Column('security_groups', Text, nullable=False),
Column('config_drive', Boolean, default=False, nullable=False),
Column('key_name', String(length=255)),
Column(
'locked_by',
Enum('owner', 'admin', name='build_requests0locked_by')),
UniqueConstraint(
'request_spec_id', name='uniq_build_requests0request_spec_id'),
Index('build_requests_project_id_idx', 'project_id'),
ForeignKeyConstraint(columns=['request_spec_id'],
refcolumns=[request_specs.c.id]),
mysql_engine='InnoDB',
mysql_charset='utf8'
)
tables = [
cell_mappings,
host_mappings,
instance_mappings,
flavors,
flavor_extra_specs,
flavor_projects,
request_specs,
build_requests,
]
for table in tables:
table.create(checkfirst=True)

View File

@ -30,7 +30,7 @@ from nova.i18n import _
INIT_VERSION = {}
INIT_VERSION['main'] = 401
INIT_VERSION['api'] = 2
INIT_VERSION['api'] = 6
_REPOSITORY = {}
LOG = logging.getLogger(__name__)

View File

@ -228,90 +228,6 @@ class NovaAPIMigrationsWalk(test_migrations.WalkVersionsMixin):
self.assertRaises(sqlalchemy.exc.NoSuchTableError,
db_utils.get_table, engine, table_name)
def _check_004(self, engine, data):
columns = ['created_at', 'updated_at', 'id', 'instance_uuid', 'spec']
for column in columns:
self.assertColumnExists(engine, 'request_specs', column)
self.assertUniqueConstraintExists(engine, 'request_specs',
['instance_uuid'])
self.assertIndexExists(engine, 'request_specs',
'request_spec_instance_uuid_idx')
def _check_005(self, engine, data):
# flavors
for column in ['created_at', 'updated_at', 'name', 'id', 'memory_mb',
'vcpus', 'swap', 'vcpu_weight', 'flavorid', 'rxtx_factor',
'root_gb', 'ephemeral_gb', 'disabled', 'is_public']:
self.assertColumnExists(engine, 'flavors', column)
self.assertUniqueConstraintExists(engine, 'flavors',
['flavorid'])
self.assertUniqueConstraintExists(engine, 'flavors',
['name'])
# flavor_extra_specs
for column in ['created_at', 'updated_at', 'id', 'flavor_id', 'key',
'value']:
self.assertColumnExists(engine, 'flavor_extra_specs', column)
self.assertIndexExists(engine, 'flavor_extra_specs',
'flavor_extra_specs_flavor_id_key_idx')
self.assertUniqueConstraintExists(engine, 'flavor_extra_specs',
['flavor_id', 'key'])
inspector = reflection.Inspector.from_engine(engine)
# There should only be one foreign key here
fk = inspector.get_foreign_keys('flavor_extra_specs')[0]
self.assertEqual('flavors', fk['referred_table'])
self.assertEqual(['id'], fk['referred_columns'])
self.assertEqual(['flavor_id'], fk['constrained_columns'])
# flavor_projects
for column in ['created_at', 'updated_at', 'id', 'flavor_id',
'project_id']:
self.assertColumnExists(engine, 'flavor_projects', column)
self.assertUniqueConstraintExists(engine, 'flavor_projects',
['flavor_id', 'project_id'])
inspector = reflection.Inspector.from_engine(engine)
# There should only be one foreign key here
fk = inspector.get_foreign_keys('flavor_projects')[0]
self.assertEqual('flavors', fk['referred_table'])
self.assertEqual(['id'], fk['referred_columns'])
self.assertEqual(['flavor_id'], fk['constrained_columns'])
def _check_006(self, engine, data):
for column in ['id', 'request_spec_id', 'project_id', 'user_id',
'display_name', 'instance_metadata', 'progress', 'vm_state',
'image_ref', 'access_ip_v4', 'access_ip_v6', 'info_cache',
'security_groups', 'config_drive', 'key_name', 'locked_by']:
self.assertColumnExists(engine, 'build_requests', column)
self.assertIndexExists(engine, 'build_requests',
'build_requests_project_id_idx')
self.assertUniqueConstraintExists(engine, 'build_requests',
['request_spec_id'])
inspector = reflection.Inspector.from_engine(engine)
# There should only be one foreign key here
fk = inspector.get_foreign_keys('build_requests')[0]
self.assertEqual('request_specs', fk['referred_table'])
self.assertEqual(['id'], fk['referred_columns'])
self.assertEqual(['request_spec_id'], fk['constrained_columns'])
def _check_007(self, engine, data):
map_table = db_utils.get_table(engine, 'instance_mappings')
self.assertTrue(map_table.columns['cell_id'].nullable)
# Ensure the foreign key still exists
inspector = reflection.Inspector.from_engine(engine)
# There should only be one foreign key here
fk = inspector.get_foreign_keys('instance_mappings')[0]
self.assertEqual('cell_mappings', fk['referred_table'])
self.assertEqual(['id'], fk['referred_columns'])
self.assertEqual(['cell_id'], fk['constrained_columns'])
def _check_013(self, engine, data):
for column in ['instance_uuid', 'instance']:
self.assertColumnExists(engine, 'build_requests', column)