apidb: Compact Newton database migrations

Specific changes include:

- Add 'instance_uuid' and 'instance' columns to 'build_requests' table
  (013)
- Add index covering 'instance_uuid' column of 'build_requests' table
  (013)
- Add unique constraint covering 'instance_uuid' column of
  'build_requests' table (013)
- Add 'keypairs' table (014)
- Drop foreign key constraint covering 'request_spec_id' of
  'build_requests' table (015)
- Drop unique constraint covering 'request_spec_id' of 'build_requests'
  table (015)
- Alter 'request_spec_id', 'user_id', 'security_groups' and
  'config_drive' columns of 'build_requests' table to be nullable (015)
- Add 'resource_providers', 'inventories', 'allocations', and
  'resource_provider_aggregates' tables (016)
- Add 'aggregate', 'aggregate_hosts' and 'aggregate_metadata' tables
  (017)
- Add 'groups', 'group_policy' and 'group_member' tables (018)
- Add 'block_device_mappings' column to 'build_requests' table (019)
- Alter 'block_device_mappings' column of 'build_requests' table to be
  'MediumText' (020)

Change-Id: I944a0ed33d9ac8bda81a4e09a33e8fd768b6f95d
Signed-off-by: Stephen Finucane <stephenfin@redhat.com>
This commit is contained in:
Stephen Finucane 2020-10-22 15:46:29 +01:00
parent d2449232bd
commit 302f2bc4f7
17 changed files with 392 additions and 900 deletions

View File

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

@ -1,23 +0,0 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
# This is a placeholder for backports.
# Do not use this number for new work. New work starts after
# all the placeholders.
#
# See this for more information:
# http://lists.openstack.org/pipermail/openstack-dev/2013-March/006827.html
def upgrade(migrate_engine):
pass

View File

@ -1,23 +0,0 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
# This is a placeholder for backports.
# Do not use this number for new work. New work starts after
# all the placeholders.
#
# See this for more information:
# http://lists.openstack.org/pipermail/openstack-dev/2013-March/006827.html
def upgrade(migrate_engine):
pass

View File

@ -1,23 +0,0 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
# This is a placeholder for backports.
# Do not use this number for new work. New work starts after
# all the placeholders.
#
# See this for more information:
# http://lists.openstack.org/pipermail/openstack-dev/2013-March/006827.html
def upgrade(migrate_engine):
pass

View File

@ -1,23 +0,0 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
# This is a placeholder for backports.
# Do not use this number for new work. New work starts after
# all the placeholders.
#
# See this for more information:
# http://lists.openstack.org/pipermail/openstack-dev/2013-March/006827.html
def upgrade(migrate_engine):
pass

View File

@ -1,23 +0,0 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
# This is a placeholder for backports.
# Do not use this number for new work. New work starts after
# all the placeholders.
#
# See this for more information:
# http://lists.openstack.org/pipermail/openstack-dev/2013-March/006827.html
def upgrade(migrate_engine):
pass

View File

@ -1,52 +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.engine import reflection
from sqlalchemy import Index
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
build_requests = Table('build_requests', meta, autoload=True)
columns_to_add = [
('instance_uuid',
Column('instance_uuid', String(length=36))),
('instance',
Column('instance', Text())),
]
for (col_name, column) in columns_to_add:
if not hasattr(build_requests.c, col_name):
build_requests.create_column(column)
for index in build_requests.indexes:
if [c.name for c in index.columns] == ['instance_uuid']:
break
else:
index = Index('build_requests_instance_uuid_idx',
build_requests.c.instance_uuid)
index.create()
inspector = reflection.Inspector.from_engine(migrate_engine)
constrs = inspector.get_unique_constraints('build_requests')
constr_names = [constr['name'] for constr in constrs]
if 'uniq_build_requests0instance_uuid' not in constr_names:
UniqueConstraint('instance_uuid', table=build_requests,
name='uniq_build_requests0instance_uuid').create()

View File

@ -1,48 +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 Enum
from sqlalchemy import Integer
from sqlalchemy import MetaData
from sqlalchemy import String
from sqlalchemy import Table
from sqlalchemy import Text
from nova.objects import keypair
def upgrade(migrate_engine):
meta = MetaData()
meta.bind = migrate_engine
enum = Enum('ssh', 'x509', metadata=meta, name='keypair_types')
enum.create(checkfirst=True)
keypairs = Table('key_pairs', meta,
Column('created_at', DateTime),
Column('updated_at', DateTime),
Column('id', Integer, primary_key=True, nullable=False),
Column('name', String(255), nullable=False),
Column('user_id', String(255), nullable=False),
Column('fingerprint', String(255)),
Column('public_key', Text()),
Column('type', enum, nullable=False,
server_default=keypair.KEYPAIR_TYPE_SSH),
UniqueConstraint('user_id', 'name',
name="uniq_key_pairs0user_id0name"),
mysql_engine='InnoDB',
mysql_charset='utf8'
)
keypairs.create(checkfirst=True)

View File

@ -1,48 +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.engine import reflection
from sqlalchemy import MetaData
from sqlalchemy import Table
def upgrade(migrate_engine):
meta = MetaData()
meta.bind = migrate_engine
build_requests = Table('build_requests', meta, autoload=True)
request_specs = Table('request_specs', meta, autoload=True)
for fkey in build_requests.foreign_keys:
if fkey.target_fullname == 'request_specs.id':
ForeignKeyConstraint(columns=['request_spec_id'],
refcolumns=[request_specs.c.id],
table=build_requests,
name=fkey.name).drop()
break
# These are being made nullable because they are no longer used after the
# addition of the instance column. However they need a deprecation period
# before they can be dropped.
columns_to_nullify = ['request_spec_id', 'user_id', 'security_groups',
'config_drive']
for column in columns_to_nullify:
getattr(build_requests.c, column).alter(nullable=True)
inspector = reflection.Inspector.from_engine(migrate_engine)
constrs = inspector.get_unique_constraints('build_requests')
constr_names = [constr['name'] for constr in constrs]
if 'uniq_build_requests0request_spec_id' in constr_names:
UniqueConstraint('request_spec_id', table=build_requests,
name='uniq_build_requests0request_spec_id').drop()

View File

@ -1,110 +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.
"""Database migrations for resource-providers."""
from migrate import UniqueConstraint
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
from sqlalchemy import Unicode
def upgrade(migrate_engine):
meta = MetaData()
meta.bind = migrate_engine
if migrate_engine.name == 'mysql':
nameargs = {'collation': 'utf8_bin'}
else:
nameargs = {}
resource_providers = Table(
'resource_providers', meta,
Column('created_at', DateTime),
Column('updated_at', DateTime),
Column('id', Integer, primary_key=True, nullable=False),
Column('uuid', String(36), nullable=False),
Column('name', Unicode(200, **nameargs), nullable=True),
Column('generation', Integer, default=0),
Column('can_host', Integer, default=0),
UniqueConstraint('uuid', name='uniq_resource_providers0uuid'),
UniqueConstraint('name', name='uniq_resource_providers0name'),
Index('resource_providers_name_idx', 'name'),
Index('resource_providers_uuid_idx', 'uuid'),
mysql_engine='InnoDB',
mysql_charset='latin1'
)
inventories = Table(
'inventories', meta,
Column('created_at', DateTime),
Column('updated_at', DateTime),
Column('id', Integer, primary_key=True, nullable=False),
Column('resource_provider_id', Integer, nullable=False),
Column('resource_class_id', Integer, nullable=False),
Column('total', Integer, nullable=False),
Column('reserved', Integer, nullable=False),
Column('min_unit', Integer, nullable=False),
Column('max_unit', Integer, nullable=False),
Column('step_size', Integer, nullable=False),
Column('allocation_ratio', Float, nullable=False),
Index('inventories_resource_provider_id_idx',
'resource_provider_id'),
Index('inventories_resource_provider_resource_class_idx',
'resource_provider_id', 'resource_class_id'),
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'
)
allocations = Table(
'allocations', meta,
Column('created_at', DateTime),
Column('updated_at', DateTime),
Column('id', Integer, primary_key=True, nullable=False),
Column('resource_provider_id', Integer, nullable=False),
Column('consumer_id', String(36), nullable=False),
Column('resource_class_id', Integer, nullable=False),
Column('used', Integer, nullable=False),
Index('allocations_resource_provider_class_used_idx',
'resource_provider_id', 'resource_class_id',
'used'),
Index('allocations_resource_class_id_idx',
'resource_class_id'),
Index('allocations_consumer_id_idx', 'consumer_id'),
mysql_engine='InnoDB',
mysql_charset='latin1'
)
resource_provider_aggregates = Table(
'resource_provider_aggregates', meta,
Column('created_at', DateTime),
Column('updated_at', DateTime),
Column('resource_provider_id', Integer, primary_key=True,
nullable=False),
Column('aggregate_id', Integer, primary_key=True, nullable=False),
Index('resource_provider_aggregates_aggregate_id_idx',
'aggregate_id'),
mysql_engine='InnoDB',
mysql_charset='latin1'
)
for table in [resource_providers, inventories, allocations,
resource_provider_aggregates]:
table.create(checkfirst=True)

View File

@ -1,73 +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.
"""API Database migrations for aggregates"""
from migrate import UniqueConstraint
from sqlalchemy import Column
from sqlalchemy import DateTime
from sqlalchemy import ForeignKey
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
aggregates = Table('aggregates', meta,
Column('created_at', DateTime),
Column('updated_at', DateTime),
Column('id', Integer, primary_key=True, nullable=False),
Column('uuid', String(length=36)),
Column('name', String(length=255)),
Index('aggregate_uuid_idx', 'uuid'),
UniqueConstraint('name', name='uniq_aggregate0name'),
mysql_engine='InnoDB',
mysql_charset='utf8'
)
aggregates.create(checkfirst=True)
aggregate_hosts = Table('aggregate_hosts', meta,
Column('created_at', DateTime),
Column('updated_at', DateTime),
Column('id', Integer, primary_key=True, nullable=False),
Column('host', String(length=255)),
Column('aggregate_id', Integer, ForeignKey('aggregates.id'),
nullable=False),
UniqueConstraint('host', 'aggregate_id',
name='uniq_aggregate_hosts0host0aggregate_id'),
mysql_engine='InnoDB',
mysql_charset='utf8'
)
aggregate_hosts.create(checkfirst=True)
aggregate_metadata = Table('aggregate_metadata', meta,
Column('created_at', DateTime),
Column('updated_at', DateTime),
Column('id', Integer, primary_key=True, nullable=False),
Column('aggregate_id', Integer, ForeignKey('aggregates.id'),
nullable=False),
Column('key', String(length=255), nullable=False),
Column('value', String(length=255), nullable=False),
UniqueConstraint('aggregate_id', 'key',
name='uniq_aggregate_metadata0aggregate_id0key'),
Index('aggregate_metadata_key_idx', 'key'),
mysql_engine='InnoDB',
mysql_charset='utf8'
)
aggregate_metadata.create(checkfirst=True)

View File

@ -1,71 +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.
"""API Database migrations for instance_groups"""
from migrate import UniqueConstraint
from sqlalchemy import Column
from sqlalchemy import DateTime
from sqlalchemy import ForeignKey
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
groups = Table('instance_groups', meta,
Column('created_at', DateTime),
Column('updated_at', DateTime),
Column('id', Integer, primary_key=True, nullable=False),
Column('user_id', String(length=255)),
Column('project_id', String(length=255)),
Column('uuid', String(length=36), nullable=False),
Column('name', String(length=255)),
UniqueConstraint('uuid',
name='uniq_instance_groups0uuid'),
mysql_engine='InnoDB',
mysql_charset='utf8',
)
groups.create(checkfirst=True)
group_policy = Table('instance_group_policy', meta,
Column('created_at', DateTime),
Column('updated_at', DateTime),
Column('id', Integer, primary_key=True, nullable=False),
Column('policy', String(length=255)),
Column('group_id', Integer, ForeignKey('instance_groups.id'),
nullable=False),
Index('instance_group_policy_policy_idx', 'policy'),
mysql_engine='InnoDB',
mysql_charset='utf8',
)
group_policy.create(checkfirst=True)
group_member = Table('instance_group_member', meta,
Column('created_at', DateTime),
Column('updated_at', DateTime),
Column('id', Integer, primary_key=True, nullable=False),
Column('instance_uuid', String(length=255)),
Column('group_id', Integer, ForeignKey('instance_groups.id'),
nullable=False),
Index('instance_group_member_instance_idx', 'instance_uuid'),
mysql_engine='InnoDB',
mysql_charset='utf8',
)
group_member.create(checkfirst=True)

View File

@ -1,26 +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 Column
from sqlalchemy import MetaData
from sqlalchemy import Table
from sqlalchemy import Text
def upgrade(migrate_engine):
meta = MetaData()
meta.bind = migrate_engine
build_requests = Table('build_requests', meta, autoload=True)
if not hasattr(build_requests.c, 'block_device_mappings'):
build_requests.create_column(Column('block_device_mappings', Text()))

View File

@ -1,24 +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
from nova.db.sqlalchemy import api_models
def upgrade(migrate_engine):
meta = MetaData()
meta.bind = migrate_engine
build_requests = Table('build_requests', meta, autoload=True)
build_requests.c.block_device_mappings.alter(type=api_models.MediumText())

View File

@ -0,0 +1,390 @@
# 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 ForeignKey
from sqlalchemy import Index
from sqlalchemy import Integer
from sqlalchemy import MetaData
from sqlalchemy import String
from sqlalchemy import Table
from sqlalchemy import Text
from sqlalchemy import Unicode
from nova.db.sqlalchemy.api_models import MediumText
from nova.objects import keypair
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=True),
Column('project_id', String(length=255), nullable=False),
Column('user_id', String(length=255), nullable=True),
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=True),
Column('config_drive', Boolean, default=False, nullable=True),
Column('key_name', String(length=255)),
Column(
'locked_by',
Enum('owner', 'admin', name='build_requests0locked_by')),
Column('instance_uuid', String(length=36)),
Column('instance', Text()),
Column('block_device_mappings', MediumText()),
UniqueConstraint(
'instance_uuid', name='uniq_build_requests0instance_uuid'),
Index('build_requests_project_id_idx', 'project_id'),
Index('build_requests_instance_uuid_idx', 'instance_uuid'),
mysql_engine='InnoDB',
mysql_charset='utf8'
)
keypairs = Table('key_pairs', meta,
Column('created_at', DateTime),
Column('updated_at', DateTime),
Column('id', Integer, primary_key=True, nullable=False),
Column('name', String(255), nullable=False),
Column('user_id', String(255), nullable=False),
Column('fingerprint', String(255)),
Column('public_key', Text()),
Column(
'type', 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'
)
nameargs = {}
if migrate_engine.name == 'mysql':
nameargs['collation'] = 'utf8_bin'
resource_providers = Table(
'resource_providers', meta,
Column('created_at', DateTime),
Column('updated_at', DateTime),
Column('id', Integer, primary_key=True, nullable=False),
Column('uuid', String(36), nullable=False),
Column('name', Unicode(200, **nameargs), nullable=True),
Column('generation', Integer, default=0),
Column('can_host', Integer, default=0),
UniqueConstraint('uuid', name='uniq_resource_providers0uuid'),
UniqueConstraint('name', name='uniq_resource_providers0name'),
Index('resource_providers_name_idx', 'name'),
Index('resource_providers_uuid_idx', 'uuid'),
mysql_engine='InnoDB',
mysql_charset='latin1'
)
inventories = Table(
'inventories', meta,
Column('created_at', DateTime),
Column('updated_at', DateTime),
Column('id', Integer, primary_key=True, nullable=False),
Column('resource_provider_id', Integer, nullable=False),
Column('resource_class_id', Integer, nullable=False),
Column('total', Integer, nullable=False),
Column('reserved', Integer, nullable=False),
Column('min_unit', Integer, nullable=False),
Column('max_unit', Integer, nullable=False),
Column('step_size', Integer, nullable=False),
Column('allocation_ratio', Float, nullable=False),
Index(
'inventories_resource_provider_id_idx', 'resource_provider_id'),
Index(
'inventories_resource_provider_resource_class_idx',
'resource_provider_id', 'resource_class_id'),
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'
)
allocations = Table(
'allocations', meta,
Column('created_at', DateTime),
Column('updated_at', DateTime),
Column('id', Integer, primary_key=True, nullable=False),
Column('resource_provider_id', Integer, nullable=False),
Column('consumer_id', String(36), nullable=False),
Column('resource_class_id', Integer, nullable=False),
Column('used', Integer, nullable=False),
Index(
'allocations_resource_provider_class_used_idx',
'resource_provider_id', 'resource_class_id', 'used'),
Index(
'allocations_resource_class_id_idx', 'resource_class_id'),
Index('allocations_consumer_id_idx', 'consumer_id'),
mysql_engine='InnoDB',
mysql_charset='latin1'
)
resource_provider_aggregates = Table(
'resource_provider_aggregates', meta,
Column('created_at', DateTime),
Column('updated_at', DateTime),
Column(
'resource_provider_id', Integer, primary_key=True, nullable=False),
Column('aggregate_id', Integer, primary_key=True, nullable=False),
Index(
'resource_provider_aggregates_aggregate_id_idx', 'aggregate_id'),
mysql_engine='InnoDB',
mysql_charset='latin1'
)
aggregates = Table('aggregates', meta,
Column('created_at', DateTime),
Column('updated_at', DateTime),
Column('id', Integer, primary_key=True, nullable=False),
Column('uuid', String(length=36)),
Column('name', String(length=255)),
Index('aggregate_uuid_idx', 'uuid'),
UniqueConstraint('name', name='uniq_aggregate0name'),
mysql_engine='InnoDB',
mysql_charset='utf8'
)
aggregate_hosts = Table('aggregate_hosts', meta,
Column('created_at', DateTime),
Column('updated_at', DateTime),
Column('id', Integer, primary_key=True, nullable=False),
Column('host', String(length=255)),
Column(
'aggregate_id', Integer, ForeignKey('aggregates.id'),
nullable=False),
UniqueConstraint(
'host', 'aggregate_id',
name='uniq_aggregate_hosts0host0aggregate_id'),
mysql_engine='InnoDB',
mysql_charset='utf8'
)
aggregate_metadata = Table('aggregate_metadata', meta,
Column('created_at', DateTime),
Column('updated_at', DateTime),
Column('id', Integer, primary_key=True, nullable=False),
Column(
'aggregate_id', Integer, ForeignKey('aggregates.id'),
nullable=False),
Column('key', String(length=255), nullable=False),
Column('value', String(length=255), nullable=False),
UniqueConstraint(
'aggregate_id', 'key',
name='uniq_aggregate_metadata0aggregate_id0key'),
Index('aggregate_metadata_key_idx', 'key'),
mysql_engine='InnoDB',
mysql_charset='utf8'
)
groups = Table('instance_groups', meta,
Column('created_at', DateTime),
Column('updated_at', DateTime),
Column('id', Integer, primary_key=True, nullable=False),
Column('user_id', String(length=255)),
Column('project_id', String(length=255)),
Column('uuid', String(length=36), nullable=False),
Column('name', String(length=255)),
UniqueConstraint(
'uuid', name='uniq_instance_groups0uuid'),
mysql_engine='InnoDB',
mysql_charset='utf8',
)
group_policy = Table('instance_group_policy', meta,
Column('created_at', DateTime),
Column('updated_at', DateTime),
Column('id', Integer, primary_key=True, nullable=False),
Column('policy', String(length=255)),
Column(
'group_id', Integer, ForeignKey('instance_groups.id'),
nullable=False),
Index('instance_group_policy_policy_idx', 'policy'),
mysql_engine='InnoDB',
mysql_charset='utf8',
)
group_member = Table('instance_group_member', meta,
Column('created_at', DateTime),
Column('updated_at', DateTime),
Column('id', Integer, primary_key=True, nullable=False),
Column('instance_uuid', String(length=255)),
Column(
'group_id', Integer, ForeignKey('instance_groups.id'),
nullable=False),
Index('instance_group_member_instance_idx', 'instance_uuid'),
mysql_engine='InnoDB',
mysql_charset='utf8',
)
tables = [
cell_mappings,
host_mappings,
instance_mappings,
flavors,
flavor_extra_specs,
flavor_projects,
request_specs,
build_requests,
keypairs,
resource_providers,
inventories,
allocations,
resource_provider_aggregates,
aggregates,
aggregate_hosts,
aggregate_metadata,
groups,
group_policy,
group_member,
]
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'] = 6
INIT_VERSION['api'] = 19
_REPOSITORY = {}
LOG = logging.getLogger(__name__)

View File

@ -172,7 +172,6 @@ class NovaAPIMigrationsWalk(test_migrations.WalkVersionsMixin):
return self.engine
def _skippable_migrations(self):
mitaka_placeholders = list(range(8, 13))
newton_placeholders = list(range(21, 26))
ocata_placeholders = list(range(31, 41))
pike_placeholders = list(range(45, 50))
@ -186,8 +185,7 @@ class NovaAPIMigrationsWalk(test_migrations.WalkVersionsMixin):
self.INIT_VERSION + 1, # initial change
30, # Enforcement migration, no changes to test
]
return (mitaka_placeholders +
newton_placeholders +
return (newton_placeholders +
ocata_placeholders +
pike_placeholders +
queens_placeholders +
@ -228,144 +226,6 @@ class NovaAPIMigrationsWalk(test_migrations.WalkVersionsMixin):
self.assertRaises(sqlalchemy.exc.NoSuchTableError,
db_utils.get_table, engine, table_name)
def _check_013(self, engine, data):
for column in ['instance_uuid', 'instance']:
self.assertColumnExists(engine, 'build_requests', column)
self.assertIndexExists(engine, 'build_requests',
'build_requests_instance_uuid_idx')
self.assertUniqueConstraintExists(engine, 'build_requests',
['instance_uuid'])
def _check_014(self, engine, data):
for column in ['name', 'public_key']:
self.assertColumnExists(engine, 'key_pairs', column)
self.assertUniqueConstraintExists(engine, 'key_pairs',
['user_id', 'name'])
def _check_015(self, engine, data):
build_requests_table = db_utils.get_table(engine, 'build_requests')
for column in ['request_spec_id', 'user_id', 'security_groups',
'config_drive']:
self.assertTrue(build_requests_table.columns[column].nullable)
inspector = reflection.Inspector.from_engine(engine)
constrs = inspector.get_unique_constraints('build_requests')
constr_columns = [constr['column_names'] for constr in constrs]
self.assertNotIn(['request_spec_id'], constr_columns)
def _check_016(self, engine, data):
self.assertColumnExists(engine, 'resource_providers', 'id')
self.assertIndexExists(engine, 'resource_providers',
'resource_providers_name_idx')
self.assertIndexExists(engine, 'resource_providers',
'resource_providers_uuid_idx')
self.assertColumnExists(engine, 'inventories', 'id')
self.assertIndexExists(engine, 'inventories',
'inventories_resource_class_id_idx')
self.assertColumnExists(engine, 'allocations', 'id')
self.assertColumnExists(engine, 'resource_provider_aggregates',
'aggregate_id')
def _check_017(self, engine, data):
# aggregate_metadata
for column in ['created_at',
'updated_at',
'id',
'aggregate_id',
'key',
'value']:
self.assertColumnExists(engine, 'aggregate_metadata', column)
self.assertUniqueConstraintExists(engine, 'aggregate_metadata',
['aggregate_id', 'key'])
self.assertIndexExists(engine, 'aggregate_metadata',
'aggregate_metadata_key_idx')
# aggregate_hosts
for column in ['created_at',
'updated_at',
'id',
'host',
'aggregate_id']:
self.assertColumnExists(engine, 'aggregate_hosts', column)
self.assertUniqueConstraintExists(engine, 'aggregate_hosts',
['host', 'aggregate_id'])
# aggregates
for column in ['created_at',
'updated_at',
'id',
'name']:
self.assertColumnExists(engine, 'aggregates', column)
self.assertIndexExists(engine, 'aggregates',
'aggregate_uuid_idx')
self.assertUniqueConstraintExists(engine, 'aggregates', ['name'])
def _check_018(self, engine, data):
# instance_groups
for column in ['created_at',
'updated_at',
'id',
'user_id',
'project_id',
'uuid',
'name']:
self.assertColumnExists(engine, 'instance_groups', column)
self.assertUniqueConstraintExists(engine, 'instance_groups', ['uuid'])
# instance_group_policy
for column in ['created_at',
'updated_at',
'id',
'policy',
'group_id']:
self.assertColumnExists(engine, 'instance_group_policy', column)
self.assertIndexExists(engine, 'instance_group_policy',
'instance_group_policy_policy_idx')
# 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_group_policy')[0]
self.assertEqual('instance_groups', fk['referred_table'])
self.assertEqual(['id'], fk['referred_columns'])
# instance_group_member
for column in ['created_at',
'updated_at',
'id',
'instance_uuid',
'group_id']:
self.assertColumnExists(engine, 'instance_group_member', column)
self.assertIndexExists(engine, 'instance_group_member',
'instance_group_member_instance_idx')
def _check_019(self, engine, data):
self.assertColumnExists(engine, 'build_requests',
'block_device_mappings')
def _pre_upgrade_020(self, engine):
build_requests = db_utils.get_table(engine, 'build_requests')
fake_build_req = {'id': 2020,
'project_id': 'fake_proj_id',
'block_device_mappings': 'fake_BDM'}
build_requests.insert().execute(fake_build_req)
def _check_020(self, engine, data):
build_requests = db_utils.get_table(engine, 'build_requests')
if engine.name == 'mysql':
self.assertIsInstance(build_requests.c.block_device_mappings.type,
sqlalchemy.dialects.mysql.MEDIUMTEXT)
fake_build_req = build_requests.select(
build_requests.c.id == 2020).execute().first()
self.assertEqual('fake_BDM', fake_build_req.block_device_mappings)
def _check_026(self, engine, data):
self.assertColumnExists(engine, 'resource_classes', 'id')
self.assertColumnExists(engine, 'resource_classes', 'name')