db: Compact Mitaka database migrations

Compact Mitaka database migrations into a single migration,
'319_mitaka.py'.

Users will now need to update to Mitaka before updating to Newton or
later.

Specific changes include:

- Add 'parent_addr' column to 'pci_devices' table
- Add 'resource_providers', 'inventories', and 'allocations' tables
- Add 'memory_total', 'memory_processed', 'memory_remaining', 'disk_total',
  'disk_processed', and 'disk_remaining' columns to 'migrations' table
- Add 'disk_allocation_ratio' column to 'compute_nodes' table
- Add 'uuid' column and corresponding index to 'aggregates' table
- Add 'name', 'generation' and 'can_host' columns to
  'resource_providers' table
- Add unique constraint on 'name' column of 'resource_providers' table
- Add index on 'name' column of 'resource_providers' table
- Add 'resource_provider_aggregates' table

Some tests that depended on some of these migrations are removed.

When testing, the previous base version was 301. It is now 318.

Change-Id: Ib0c9229899e9a83992757270503e0e1a988f2402
Signed-off-by: Stephen Finucane <stephenfin@redhat.com>
This commit is contained in:
Stephen Finucane 2020-10-05 11:18:11 +01:00
parent 1da542ff7a
commit 76e8653ba1
21 changed files with 98 additions and 678 deletions

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 Liberty backports.
# Do not use this number for new Mitaka 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 Liberty backports.
# Do not use this number for new Mitaka 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 Liberty backports.
# Do not use this number for new Mitaka 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 Liberty backports.
# Do not use this number for new Mitaka 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 Liberty backports.
# Do not use this number for new Mitaka 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 Liberty backports.
# Do not use this number for new Mitaka 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 Liberty backports.
# Do not use this number for new Mitaka 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 Liberty backports.
# Do not use this number for new Mitaka 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 Liberty backports.
# Do not use this number for new Mitaka 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 Liberty backports.
# Do not use this number for new Mitaka 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,40 +0,0 @@
# Copyright 2015 Red Hat Inc
# 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.
#
# See blueprint backportable-db-migrations-icehouse
# http://lists.openstack.org/pipermail/openstack-dev/2013-March/006827.html
from sqlalchemy import MetaData, Table, Column, String, Index
def upgrade(migrate_engine):
meta = MetaData(bind=migrate_engine)
# Add a new column to store PCI device parent address
pci_devices = Table('pci_devices', meta, autoload=True)
shadow_pci_devices = Table('shadow_pci_devices', meta, autoload=True)
parent_addr = Column('parent_addr', String(12), nullable=True)
if not hasattr(pci_devices.c, 'parent_addr'):
pci_devices.create_column(parent_addr)
if not hasattr(shadow_pci_devices.c, 'parent_addr'):
shadow_pci_devices.create_column(parent_addr.copy())
# Create index
parent_index = Index('ix_pci_devices_compute_node_id_parent_addr_deleted',
pci_devices.c.compute_node_id,
pci_devices.c.parent_addr,
pci_devices.c.deleted)
parent_index.create(migrate_engine)

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.
"""Database migrations for resource-providers."""
from migrate import UniqueConstraint
from sqlalchemy import Column
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
resource_providers = Table(
'resource_providers', meta,
Column('id', Integer, primary_key=True, nullable=False),
Column('uuid', String(36), nullable=False),
UniqueConstraint('uuid', name='uniq_resource_providers0uuid'),
mysql_engine='InnoDB',
mysql_charset='latin1'
)
Index('resource_providers_uuid_idx', resource_providers.c.uuid)
inventories = Table(
'inventories', meta,
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),
mysql_engine='InnoDB',
mysql_charset='latin1'
)
Index('inventories_resource_provider_id_idx',
inventories.c.resource_provider_id)
Index('inventories_resource_class_id_idx',
inventories.c.resource_class_id)
allocations = Table(
'allocations', meta,
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),
mysql_engine='InnoDB',
mysql_charset='latin1'
)
Index('allocations_resource_provider_class_id_idx',
allocations.c.resource_provider_id,
allocations.c.resource_class_id)
Index('allocations_consumer_id_idx', allocations.c.consumer_id)
Index('allocations_resource_class_id_idx',
allocations.c.resource_class_id)
for table in [resource_providers, inventories, allocations]:
table.create(checkfirst=True)
for table_name in ('', 'shadow_'):
uuid_column = Column('uuid', String(36))
compute_nodes = Table('%scompute_nodes' % table_name, meta)
compute_nodes.create_column(uuid_column)

View File

@ -1,30 +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 BigInteger
from sqlalchemy import Column
from sqlalchemy import MetaData
from sqlalchemy import Table
def upgrade(migrate_engine):
meta = MetaData(bind=migrate_engine)
migrations = Table('migrations', meta, autoload=True)
shadow_migrations = Table('shadow_migrations', meta, autoload=True)
columns = ['memory_total', 'memory_processed', 'memory_remaining',
'disk_total', 'disk_processed', 'disk_remaining']
for column_name in columns:
column = Column(column_name, BigInteger, nullable=True)
migrations.create_column(column)
shadow_migrations.create_column(column.copy())

View File

@ -1,27 +0,0 @@
# Copyright (c) 2016 Red Hat, Inc.
# All Rights Reserved.
#
# 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 Float, Column, MetaData, Table
def upgrade(migrate_engine):
meta = MetaData()
meta.bind = migrate_engine
cn = Table('compute_nodes', meta, autoload=True)
shadow_cn = Table('shadow_compute_nodes', meta, autoload=True)
cn.create_column(Column('disk_allocation_ratio', Float, nullable=True))
shadow_cn.create_column(Column('disk_allocation_ratio', Float))

View File

@ -1,32 +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 sqlalchemy import Column
from sqlalchemy import Index
from sqlalchemy import MetaData
from sqlalchemy import String
from sqlalchemy import Table
def upgrade(migrate_engine):
meta = MetaData()
meta.bind = migrate_engine
for table_prefix in ('', 'shadow_'):
uuid_column = Column('uuid', String(36))
aggregates = Table('%saggregates' % table_prefix, meta)
if not hasattr(aggregates.c, 'uuid'):
aggregates.create_column(uuid_column)
if not table_prefix:
index = Index('aggregate_uuid_idx', aggregates.c.uuid)
index.create()

View File

@ -1,90 +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 oslo_db.sqlalchemy import utils
from sqlalchemy import Column
from sqlalchemy import DDL
from sqlalchemy import Index
from sqlalchemy import Integer
from sqlalchemy import MetaData
from sqlalchemy import Table
from sqlalchemy import Unicode
def upgrade(migrate_engine):
meta = MetaData(bind=migrate_engine)
resource_providers = Table('resource_providers', meta, autoload=True)
name = Column('name', Unicode(200), nullable=True)
generation = Column('generation', Integer, default=0)
can_host = Column('can_host', Integer, default=0)
if not hasattr(resource_providers.c, 'name'):
# NOTE(cdent): The resource_providers table is defined as
# latin1 to be more efficient. Now we need the name column
# to be UTF8. First create the column, then modify it,
# otherwise the declarative handling in sqlalchemy gets
# confused.
resource_providers.create_column(name)
if migrate_engine.name == 'mysql':
name_col_ddl = DDL(
"ALTER TABLE resource_providers MODIFY name "
"VARCHAR(200) CHARACTER SET utf8")
conn = migrate_engine.connect()
conn.execute(name_col_ddl)
uc = UniqueConstraint('name', table=resource_providers,
name='uniq_resource_providers0name')
uc.create()
utils.add_index(migrate_engine, 'resource_providers',
'resource_providers_name_idx',
['name'])
if not hasattr(resource_providers.c, 'generation'):
resource_providers.create_column(generation)
if not hasattr(resource_providers.c, 'can_host'):
resource_providers.create_column(can_host)
resource_provider_aggregates = Table(
'resource_provider_aggregates', meta,
Column('resource_provider_id', Integer, primary_key=True,
nullable=False),
Column('aggregate_id', Integer, primary_key=True, nullable=False),
mysql_engine='InnoDB',
mysql_charset='latin1'
)
Index('resource_provider_aggregates_aggregate_id_idx',
resource_provider_aggregates.c.aggregate_id)
resource_provider_aggregates.create(checkfirst=True)
utils.add_index(migrate_engine, 'allocations',
'allocations_resource_provider_class_used_idx',
['resource_provider_id', 'resource_class_id',
'used'])
utils.drop_index(migrate_engine, 'allocations',
'allocations_resource_provider_class_id_idx')
# Add a unique constraint so that any resource provider can have
# only one inventory for any given resource class.
inventories = Table('inventories', meta, autoload=True)
inventories_uc = UniqueConstraint(
'resource_provider_id', 'resource_class_id', table=inventories,
name='uniq_inventories0resource_provider_resource_class')
inventories_uc.create()
utils.add_index(migrate_engine, 'inventories',
'inventories_resource_provider_resource_class_idx',
['resource_provider_id', 'resource_class_id'])

View File

@ -1,45 +0,0 @@
# Copyright 2016 IBM Corp.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from oslo_log import log as logging
from sqlalchemy import MetaData, Table, Index
LOG = logging.getLogger(__name__)
INDEX_COLUMNS = ['deleted', 'created_at']
INDEX_NAME = 'instances_deleted_created_at_idx'
def _get_table_index(migrate_engine):
meta = MetaData()
meta.bind = migrate_engine
table = Table('instances', meta, autoload=True)
for idx in table.indexes:
if idx.columns.keys() == INDEX_COLUMNS:
break
else:
idx = None
return meta, table, idx
def upgrade(migrate_engine):
meta, table, index = _get_table_index(migrate_engine)
if index:
LOG.info('Skipped adding %s because an equivalent index'
' already exists.', INDEX_NAME)
return
columns = [getattr(table.c, col_name) for col_name in INDEX_COLUMNS]
index = Index(INDEX_NAME, *columns)
index.create(migrate_engine)

View File

@ -58,7 +58,13 @@ def _create_shadow_tables(migrate_engine):
for table_name in table_names:
# Skip tables that are not soft-deletable
if table_name in ('tags', ):
if table_name in (
'tags',
'resource_providers',
'inventories',
'allocations',
'resource_provider_aggregates',
):
continue
table = Table(table_name, meta, autoload=True)
@ -184,10 +190,27 @@ def upgrade(migrate_engine):
Column('id', Integer, primary_key=True, nullable=False),
Column('name', String(length=255)),
Column('deleted', Integer),
Column('uuid', String(36)),
Index('aggregate_uuid_idx', 'uuid'),
mysql_engine='InnoDB',
mysql_charset='utf8'
)
allocations = Table('allocations', meta,
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_consumer_id_idx', 'consumer_id'),
Index('allocations_resource_class_id_idx', 'resource_class_id'),
mysql_engine='InnoDB',
mysql_charset='latin1',
)
block_device_mapping = Table('block_device_mapping', meta,
Column('created_at', DateTime),
Column('updated_at', DateTime),
@ -295,6 +318,8 @@ def upgrade(migrate_engine):
Column('host', String(255), nullable=True),
Column('ram_allocation_ratio', Float, nullable=True),
Column('cpu_allocation_ratio', Float, nullable=True),
Column('uuid', String(36), nullable=True),
Column('disk_allocation_ratio', Float, nullable=True),
UniqueConstraint(
'host', 'hypervisor_hostname', 'deleted',
name='uniq_compute_nodes0host0hypervisor_hostname0deleted',
@ -677,6 +702,30 @@ def upgrade(migrate_engine):
mysql_charset='utf8',
)
inventories = Table('inventories', meta,
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_class_id_idx', 'resource_class_id'),
Index(
'inventories_resource_provider_resource_class_idx',
'resource_provider_id', 'resource_class_id'),
UniqueConstraint(
'resource_provider_id', 'resource_class_id',
name='uniq_inventories0resource_provider_resource_class'),
mysql_engine='InnoDB',
mysql_charset='latin1',
)
key_pairs = Table('key_pairs', meta,
Column('created_at', DateTime),
Column('updated_at', DateTime),
@ -721,6 +770,12 @@ def upgrade(migrate_engine):
# NOTE(stephenfin): This was originally added by sqlalchemy-migrate
# which did not generate the constraints
Column('hidden', Boolean(create_constraint=False), default=False),
Column('memory_total', BigInteger, nullable=True),
Column('memory_processed', BigInteger, nullable=True),
Column('memory_remaining', BigInteger, nullable=True),
Column('disk_total', BigInteger, nullable=True),
Column('disk_processed', BigInteger, nullable=True),
Column('disk_remaining', BigInteger, nullable=True),
mysql_engine='InnoDB',
mysql_charset='utf8'
)
@ -785,6 +840,7 @@ def upgrade(migrate_engine):
Column('instance_uuid', String(36), nullable=True),
Column('request_id', String(36), nullable=True),
Column('numa_node', Integer, default=None),
Column('parent_addr', String(12), nullable=True),
Index('ix_pci_devices_instance_uuid_deleted',
'instance_uuid', 'deleted'),
Index('ix_pci_devices_compute_node_id_deleted',
@ -889,6 +945,29 @@ def upgrade(migrate_engine):
mysql_charset='utf8'
)
resource_providers = Table('resource_providers', meta,
Column('id', Integer, primary_key=True, nullable=False),
Column('uuid', String(36), nullable=False),
Column('name', Unicode(200), 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',
)
resource_provider_aggregates = Table('resource_provider_aggregates', meta,
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',
)
s3_images = Table('s3_images', meta,
Column('created_at', DateTime),
Column('updated_at', DateTime),
@ -1121,7 +1200,9 @@ def upgrade(migrate_engine):
services, snapshot_id_mappings, tags, task_log,
virtual_interfaces,
volume_id_mappings,
volume_usage_cache]
volume_usage_cache,
resource_providers, inventories, allocations,
resource_provider_aggregates]
for table in tables:
try:
@ -1225,6 +1306,8 @@ def upgrade(migrate_engine):
instances.c.cleaned),
Index('instances_project_id_deleted_idx',
instances.c.project_id, instances.c.deleted),
Index('instances_deleted_created_at_idx',
instances.c.deleted, instances.c.created_at),
# instance_actions
Index('instance_uuid_idx', instance_actions.c.instance_uuid),
@ -1275,6 +1358,11 @@ def upgrade(migrate_engine):
Index('networks_vlan_deleted_idx', networks.c.vlan,
networks.c.deleted),
Index('ix_pci_devices_compute_node_id_parent_addr_deleted',
pci_devices.c.compute_node_id,
pci_devices.c.parent_addr,
pci_devices.c.deleted),
# project_user_quotas
Index('project_user_quotas_project_id_deleted_idx',
project_user_quotas.c.project_id,
@ -1466,6 +1554,13 @@ def upgrade(migrate_engine):
'ALTER DATABASE `%s` DEFAULT CHARACTER SET utf8' %
migrate_engine.url.database)
# NOTE(cdent): The resource_providers table is defined as latin1 to be
# more efficient. Now we need the name column to be UTF8. We modify it
# here otherwise the declarative handling in sqlalchemy gets confused.
migrate_engine.execute(
'ALTER TABLE resource_providers MODIFY name '
'VARCHAR(200) CHARACTER SET utf8')
_create_shadow_tables(migrate_engine)
# TODO(stephenfin): Fix these various bugs in a follow-up

View File

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

View File

@ -163,7 +163,6 @@ class NovaMigrationsCheckers(test_migrations.ModelsMigrationsSync,
self.INIT_VERSION + 1,
]
liberty_placeholders = list(range(303, 313))
mitaka_placeholders = list(range(320, 330))
newton_placeholders = list(range(335, 345))
ocata_placeholders = list(range(348, 358))
@ -178,7 +177,6 @@ class NovaMigrationsCheckers(test_migrations.ModelsMigrationsSync,
victoria_placeholders = list(range(413, 418))
return (special +
liberty_placeholders +
mitaka_placeholders +
newton_placeholders +
ocata_placeholders +
@ -247,89 +245,6 @@ class NovaMigrationsCheckers(test_migrations.ModelsMigrationsSync,
def test_walk_versions(self):
self.walk_versions(snake_walk=False, downgrade=False)
def _check_313(self, engine, data):
self.assertColumnExists(engine, 'pci_devices', 'parent_addr')
self.assertColumnExists(engine, 'shadow_pci_devices', 'parent_addr')
pci_devices = oslodbutils.get_table(engine, 'pci_devices')
shadow_pci_devices = oslodbutils.get_table(
engine, 'shadow_pci_devices')
self.assertIsInstance(pci_devices.c.parent_addr.type,
sqlalchemy.types.String)
self.assertTrue(pci_devices.c.parent_addr.nullable)
self.assertIsInstance(shadow_pci_devices.c.parent_addr.type,
sqlalchemy.types.String)
self.assertTrue(shadow_pci_devices.c.parent_addr.nullable)
self.assertIndexMembers(engine, 'pci_devices',
'ix_pci_devices_compute_node_id_parent_addr_deleted',
['compute_node_id', 'parent_addr', 'deleted'])
def _check_314(self, engine, data):
self.assertColumnExists(engine, 'inventories', 'resource_class_id')
self.assertColumnExists(engine, 'allocations', 'resource_class_id')
self.assertColumnExists(engine, 'resource_providers', 'id')
self.assertColumnExists(engine, 'resource_providers', 'uuid')
self.assertColumnExists(engine, 'compute_nodes', 'uuid')
self.assertColumnExists(engine, 'shadow_compute_nodes', 'uuid')
self.assertIndexMembers(engine, 'allocations',
'allocations_resource_provider_class_id_idx',
['resource_provider_id', 'resource_class_id'])
def _check_315(self, engine, data):
self.assertColumnExists(engine, 'migrations',
'memory_total')
self.assertColumnExists(engine, 'migrations',
'memory_processed')
self.assertColumnExists(engine, 'migrations',
'memory_remaining')
self.assertColumnExists(engine, 'migrations',
'disk_total')
self.assertColumnExists(engine, 'migrations',
'disk_processed')
self.assertColumnExists(engine, 'migrations',
'disk_remaining')
def _check_316(self, engine, data):
self.assertColumnExists(engine, 'compute_nodes',
'disk_allocation_ratio')
def _check_317(self, engine, data):
self.assertColumnExists(engine, 'aggregates', 'uuid')
self.assertColumnExists(engine, 'shadow_aggregates', 'uuid')
def _check_318(self, engine, data):
self.assertColumnExists(engine, 'resource_providers', 'name')
self.assertColumnExists(engine, 'resource_providers', 'generation')
self.assertColumnExists(engine, 'resource_providers', 'can_host')
self.assertIndexMembers(engine, 'resource_providers',
'resource_providers_name_idx',
['name'])
self.assertColumnExists(engine, 'resource_provider_aggregates',
'resource_provider_id')
self.assertColumnExists(engine, 'resource_provider_aggregates',
'aggregate_id')
self.assertIndexMembers(engine, 'resource_provider_aggregates',
'resource_provider_aggregates_aggregate_id_idx',
['aggregate_id'])
self.assertIndexMembers(engine, 'resource_provider_aggregates',
'resource_provider_aggregates_aggregate_id_idx',
['aggregate_id'])
self.assertIndexMembers(engine, 'inventories',
'inventories_resource_provider_resource_class_idx',
['resource_provider_id', 'resource_class_id'])
def _check_319(self, engine, data):
self.assertIndexMembers(engine, 'instances',
'instances_deleted_created_at_idx',
['deleted', 'created_at'])
def _check_330(self, engine, data):
# Just a sanity-check migration
pass

View File

@ -217,31 +217,6 @@ class TestDatabaseFixture(testtools.TestCase):
schema = "".join(line for line in conn.connection.iterdump())
self.assertEqual("BEGIN TRANSACTION;COMMIT;", schema)
def test_fixture_schema_version(self):
self.useFixture(conf_fixture.ConfFixture())
# In/after 317 aggregates did have uuid
self.useFixture(fixtures.Database(version=318))
engine = session.get_engine()
engine.connect()
meta = sqlalchemy.MetaData(engine)
aggregate = sqlalchemy.Table('aggregates', meta, autoload=True)
self.assertTrue(hasattr(aggregate.c, 'uuid'))
# Before 317, aggregates had no uuid
self.useFixture(fixtures.Database(version=316))
engine = session.get_engine()
engine.connect()
meta = sqlalchemy.MetaData(engine)
aggregate = sqlalchemy.Table('aggregates', meta, autoload=True)
self.assertFalse(hasattr(aggregate.c, 'uuid'))
engine.dispose()
def test_fixture_after_database_fixture(self):
self.useFixture(conf_fixture.ConfFixture())
self.useFixture(fixtures.Database())
self.useFixture(fixtures.Database(version=318))
class TestDefaultFlavorsFixture(testtools.TestCase):
@mock.patch("nova.objects.flavor.Flavor._send_notification")