Compact DB migrations to Queens

This compacts all database migrations up to Queens into one initial
schema to remove the need to apply every database change along the way.

Change-Id: I45f3f9ab1b6f931fcda9a64ae71bb479b250fbe3
Signed-off-by: Sean McGinnis <sean.mcginnis@gmail.com>
This commit is contained in:
Sean McGinnis 2019-05-02 22:16:29 -05:00
parent ea835e1550
commit 883e785375
No known key found for this signature in database
GPG Key ID: CE7EE4BFAF8D70C8
30 changed files with 80 additions and 914 deletions

View File

@ -26,7 +26,7 @@ from stevedore import driver
from cinder.db.sqlalchemy import api as db_api
INIT_VERSION = 96
INIT_VERSION = 122
_IMPL = None
_LOCK = threading.Lock()

View File

@ -1,20 +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 oslo_db.sqlalchemy import utils
def upgrade(migrate_engine):
if not utils.index_exists_on_columns(
migrate_engine, 'messages', ['expires_at']):
utils.add_index(migrate_engine, 'messages',
'messages_expire_at_idx', ['expires_at'])

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.
from sqlalchemy import MetaData, Table, Column, Text
def upgrade(migrate_engine):
meta = MetaData(migrate_engine)
# Add connection_info column to attachment table
attachment = Table('volume_attachment', meta, autoload=True)
connection_info = Column('connection_info', Text)
if not hasattr(attachment.c, 'connection_info'):
attachment.create_column(connection_info)

View File

@ -1,65 +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 oslo_db.sqlalchemy import utils
from oslo_log import log as logging
from sqlalchemy import MetaData
LOG = logging.getLogger(__name__)
def ensure_index_exists(migrate_engine, table_name, column):
index_name = table_name + '_' + column + '_idx'
columns = [column]
if utils.index_exists_on_columns(migrate_engine, table_name, columns):
LOG.info(
'Skipped adding %s because an equivalent index already exists.',
index_name
)
else:
utils.add_index(migrate_engine, table_name, index_name, columns)
def upgrade(migrate_engine):
meta = MetaData()
meta.bind = migrate_engine
for table_name, column in INDEXES_TO_CREATE:
ensure_index_exists(migrate_engine, table_name, column)
INDEXES_TO_CREATE = (
('attachment_specs', 'attachment_id'),
('cgsnapshots', 'consistencygroup_id'),
('group_snapshots', 'group_id'),
('group_type_specs', 'group_type_id'),
('group_volume_type_mapping', 'group_id'),
('group_volume_type_mapping', 'volume_type_id'),
('quality_of_service_specs', 'specs_id'),
('reservations', 'allocated_id'),
('reservations', 'usage_id'),
('snapshot_metadata', 'snapshot_id'),
('snapshots', 'cgsnapshot_id'),
('snapshots', 'group_snapshot_id'),
('snapshots', 'volume_id'),
('transfers', 'volume_id'),
('volume_admin_metadata', 'volume_id'),
('volume_attachment', 'volume_id'),
('volume_glance_metadata', 'snapshot_id'),
('volume_glance_metadata', 'volume_id'),
('volume_metadata', 'volume_id'),
('volume_type_extra_specs', 'volume_type_id'),
('volume_types', 'qos_specs_id'),
('volumes', 'consistencygroup_id'),
('volumes', 'group_id'),
('workers', 'service_id'),
)

View File

@ -1,45 +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.
*/
/* Fix replication_status field in volumes table.
There are some drivers that did not update the replication_status field on
the volumes on creation and since the scheduler was not updating them on
creation there is an inconsistency between the database and the storage
device backend.
Some of the drivers that have been detected to be missing this are:
- kaminario
- pure
- solidfire
This migration will fix this updating the volume_status field based on the
volume type's replication status.
*/
UPDATE volumes
SET replication_status='enabled'
WHERE (not volumes.deleted or volumes.deleted IS NULL)
AND volumes.replication_status='disabled'
AND EXISTS(
SELECT *
FROM volume_type_extra_specs
WHERE volumes.volume_type_id=volume_type_extra_specs.volume_type_id
AND (volume_type_extra_specs.deleted IS NULL
OR not volume_type_extra_specs.deleted)
AND volume_type_extra_specs.key='replication_enabled'
AND volume_type_extra_specs.value='<is> True'
);

View File

@ -1,28 +0,0 @@
# Copyright (C) 2017 Dell Inc. or its subsidiaries.
# 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 Column
from sqlalchemy import MetaData, String, Table
def upgrade(migrate_engine):
meta = MetaData()
meta.bind = migrate_engine
# Add replication_status column to groups table
table = Table('groups', meta, autoload=True)
if not hasattr(table.c, 'replication_status'):
new_column = Column('replication_status', String(255), nullable=True)
table.create_column(new_column)

View File

@ -1,25 +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, String, MetaData, Table
def upgrade(migrate_engine):
meta = MetaData(migrate_engine)
messages = Table('messages', meta, autoload=True)
detail_id = Column('detail_id', String(10), nullable=True)
action_id = Column('action_id', String(10), nullable=True)
if not hasattr(messages.c, 'detail_id'):
messages.create_column(detail_id)
if not hasattr(messages.c, 'action_id'):
messages.create_column(action_id)

View File

@ -1,21 +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, String, Table
def upgrade(migrate_engine):
meta = MetaData()
meta.bind = migrate_engine
messages = Table('messages', meta, autoload=True)
messages.c.project_id.alter(type=String(255))

View File

@ -1,50 +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 oslo_db.sqlalchemy import utils
from sqlalchemy import Boolean, Column, DateTime, ForeignKey, Integer
from sqlalchemy import MetaData, String, Table
def upgrade(migrate_engine):
"""Add backup_metadata table."""
meta = MetaData()
meta.bind = migrate_engine
Table('backups', meta, autoload=True)
backup_metadata = Table(
'backup_metadata', meta,
Column('created_at', DateTime(timezone=False)),
Column('updated_at', DateTime(timezone=False)),
Column('deleted_at', DateTime(timezone=False)),
Column('deleted', Boolean(), default=False),
Column('id', Integer, primary_key=True, nullable=False),
Column('backup_id', String(36),
ForeignKey('backups.id'),
nullable=False),
Column('key', String(255)),
Column('value', String(255)),
mysql_engine='InnoDB',
mysql_charset='utf8'
)
backup_metadata.create()
if not utils.index_exists_on_columns(migrate_engine,
'backup_metadata',
['backup_id']):
utils.add_index(migrate_engine,
'backup_metadata',
'backup_metadata_backup_id_idx',
['backup_id'])

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 Pike backports.
# Do not use this number for new Queens 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 Pike backports.
# Do not use this number for new Queens 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 Pike backports.
# Do not use this number for new Queens 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 Pike backports.
# Do not use this number for new Queens 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 Pike backports.
# Do not use this number for new Queens 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,31 +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 oslo_db.sqlalchemy import utils
from oslo_log import log as logging
from sqlalchemy import MetaData
LOG = logging.getLogger(__name__)
def upgrade(migrate_engine):
meta = MetaData()
meta.bind = migrate_engine
index_name = 'quota_usage_project_resource_idx'
columns = ['project_id', 'resource']
if utils.index_exists_on_columns(migrate_engine, 'quota_usages', columns):
LOG.info(
'Skipped adding %s because an equivalent index already exists.',
index_name
)
else:
utils.add_index(migrate_engine, 'quota_usages', index_name, columns)

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.
from sqlalchemy import Column
from sqlalchemy.engine.reflection import Inspector
from sqlalchemy import Index
from sqlalchemy import MetaData
from sqlalchemy import String
from sqlalchemy import Table
def upgrade(migrate_engine):
"""Add uuid column to services."""
meta = MetaData(bind=migrate_engine)
services = Table('services', meta, autoload=True)
if not hasattr(services.c, 'uuid'):
services.create_column(Column('uuid', String(36), nullable=True))
uuid_index_name = 'services_uuid_idx'
indexes = Inspector(migrate_engine).get_indexes('services')
if uuid_index_name not in (i['name'] for i in indexes):
services = Table('services', meta, autoload=True)
Index(uuid_index_name, services.c.uuid, unique=True).create()

View File

@ -1,28 +0,0 @@
# 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 oslo_db.sqlalchemy import utils
from sqlalchemy import MetaData
def upgrade(migrate_engine):
meta = MetaData()
meta.bind = migrate_engine
index_name = 'reservations_deleted_uuid_idx'
columns = ['deleted', 'uuid']
if utils.index_exists_on_columns(migrate_engine, 'reservations', columns):
return
utils.add_index(migrate_engine, 'reservations', index_name, columns)

View File

@ -1,37 +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.engine.reflection import Inspector
from sqlalchemy import ForeignKey
from sqlalchemy import Index
from sqlalchemy import MetaData
from sqlalchemy import String
from sqlalchemy import Table
def upgrade(migrate_engine):
"""Add service_uuid column to volumes."""
meta = MetaData(bind=migrate_engine)
Table('services', meta, autoload=True)
volumes = Table('volumes', meta, autoload=True)
if not hasattr(volumes.c, 'service_uuid'):
volumes.create_column(Column('service_uuid', String(36),
ForeignKey('services.uuid'),
nullable=True))
index_name = 'volumes_service_uuid_idx'
indexes = Inspector(migrate_engine).get_indexes('volumes')
if index_name not in (i['name'] for i in indexes):
volumes = Table('volumes', meta, autoload=True)
Index(index_name, volumes.c.service_uuid, volumes.c.deleted).create()

View File

@ -1,25 +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 Boolean, Column, MetaData, Table
def upgrade(migrate_engine):
"""Add shared_targets column to Volumes."""
meta = MetaData()
meta.bind = migrate_engine
volumes = Table('volumes', meta, autoload=True)
# NOTE(jdg): We use a default of True because it's harmless for a device
# that does NOT use shared_targets to be treated as if it does
if not hasattr(volumes.c, 'shared_targets'):
volumes.create_column(Column('shared_targets', Boolean, default=True))

View File

@ -1,21 +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 Text, Column, MetaData, Table
def upgrade(migrate_engine):
"""Add the connector column to the volume_attachment table."""
meta = MetaData(bind=migrate_engine)
volume_attachment = Table('volume_attachment', meta, autoload=True)
if not hasattr(volume_attachment.c, 'connector'):
volume_attachment.create_column(Column('connector', 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 Column, MetaData, String, Table
def upgrade(migrate_engine):
"""Add encryption_key_id column to Backups."""
meta = MetaData()
meta.bind = migrate_engine
backups = Table('backups', meta, autoload=True)
encryption_key_id = Column('encryption_key_id', String(length=36))
if not hasattr(backups.c, 'encryption_key_id'):
backups.create_column(encryption_key_id)

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 Queens backports.
# Do not use this number for new Rocky 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 Queens backports.
# Do not use this number for new Rocky 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 Queens backports.
# Do not use this number for new Rocky 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 Queens backports.
# Do not use this number for new Rocky 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 Queens backports.
# Do not use this number for new Rocky 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,21 +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 Boolean, Column, MetaData, Table
def upgrade(migrate_engine):
"""Add the no_snapshots column to the transfers table."""
meta = MetaData(bind=migrate_engine)
transfers = Table('transfers', meta, autoload=True)
if not hasattr(transfers.c, 'no_snapshots'):
transfers.create_column(Column('no_snapshots', Boolean, default=False))

View File

@ -60,6 +60,8 @@ def define_tables(meta):
Column('frozen', Boolean, default=False),
Column('active_backend_id', String(255)),
Column('cluster_name', String(255), nullable=True),
Column('uuid', String(36), nullable=True),
Index('services_uuid_idx', 'uuid', unique=True),
mysql_engine='InnoDB',
mysql_charset='utf8'
)
@ -95,7 +97,8 @@ def define_tables(meta):
Column('id', String(36), primary_key=True, nullable=False),
Column('consistencygroup_id', String(36),
ForeignKey('consistencygroups.id'),
nullable=False),
nullable=False,
index=True),
Column('user_id', String(255)),
Column('project_id', String(255)),
Column('name', String(255)),
@ -123,6 +126,7 @@ def define_tables(meta):
Column('status', String(length=255)),
Column('group_snapshot_id', String(36)),
Column('source_group_id', String(36)),
Column('replication_status', String(255)),
mysql_engine='InnoDB',
mysql_charset='utf8',
)
@ -136,7 +140,8 @@ def define_tables(meta):
Column('id', String(36), primary_key=True),
Column('group_id', String(36),
ForeignKey('groups.id'),
nullable=False),
nullable=False,
index=True),
Column('user_id', String(length=255)),
Column('project_id', String(length=255)),
Column('name', String(length=255)),
@ -181,12 +186,16 @@ def define_tables(meta):
Column('replication_extended_status', String(255)),
Column('replication_driver_data', String(255)),
Column('consistencygroup_id', String(36),
ForeignKey('consistencygroups.id')),
ForeignKey('consistencygroups.id'), index=True),
Column('provider_id', String(255)),
Column('multiattach', Boolean),
Column('previous_status', String(255)),
Column('cluster_name', String(255), nullable=True),
Column('group_id', String(36), ForeignKey('groups.id')),
Column('group_id', String(36), ForeignKey('groups.id'), index=True),
Column('service_uuid', String(36), ForeignKey('services.uuid'),
nullable=True),
Column('shared_targets', Boolean, default=True),
Index('volumes_service_uuid_idx', 'service_uuid', 'deleted'),
mysql_engine='InnoDB',
mysql_charset='utf8'
)
@ -199,7 +208,7 @@ def define_tables(meta):
Column('deleted', Boolean),
Column('id', String(36), primary_key=True, nullable=False),
Column('volume_id', String(36), ForeignKey('volumes.id'),
nullable=False),
nullable=False, index=True),
Column('attached_host', String(255)),
Column('instance_uuid', String(36)),
Column('mountpoint', String(255)),
@ -207,6 +216,8 @@ def define_tables(meta):
Column('detach_time', DateTime),
Column('attach_mode', String(36)),
Column('attach_status', String(255)),
Column('connection_info', Text),
Column('connector', Text),
mysql_engine='InnoDB',
mysql_charset='utf8'
)
@ -220,7 +231,8 @@ def define_tables(meta):
Column('id', Integer, primary_key=True, nullable=False),
Column('attachment_id', String(36),
ForeignKey('volume_attachment.id'),
nullable=False),
nullable=False,
index=True),
Column('key', String(255)),
Column('value', String(255)),
mysql_engine='InnoDB',
@ -236,7 +248,7 @@ def define_tables(meta):
Column('id', String(36), primary_key=True, nullable=False),
Column('volume_id', String(36),
ForeignKey('volumes.id', name='snapshots_volume_id_fkey'),
nullable=False),
nullable=False, index=True),
Column('user_id', String(255)),
Column('project_id', String(255)),
Column('status', String(255)),
@ -249,11 +261,11 @@ def define_tables(meta):
Column('encryption_key_id', String(36)),
Column('volume_type_id', String(36)),
Column('cgsnapshot_id', String(36),
ForeignKey('cgsnapshots.id')),
ForeignKey('cgsnapshots.id'), index=True),
Column('provider_id', String(255)),
Column('provider_auth', String(255)),
Column('group_snapshot_id', String(36),
ForeignKey('group_snapshots.id')),
ForeignKey('group_snapshots.id'), index=True),
mysql_engine='InnoDB',
mysql_charset='utf8'
)
@ -266,7 +278,7 @@ def define_tables(meta):
Column('deleted', Boolean),
Column('id', Integer, primary_key=True, nullable=False),
Column('snapshot_id', String(36), ForeignKey('snapshots.id'),
nullable=False),
nullable=False, index=True),
Column('key', String(255)),
Column('value', String(255)),
mysql_engine='InnoDB',
@ -281,7 +293,8 @@ def define_tables(meta):
Column('deleted', Boolean(create_constraint=True, name=None)),
Column('id', String(36), primary_key=True, nullable=False),
Column('specs_id', String(36),
ForeignKey('quality_of_service_specs.id')),
ForeignKey('quality_of_service_specs.id'),
index=True),
Column('key', String(255)),
Column('value', String(255)),
mysql_engine='InnoDB',
@ -297,7 +310,7 @@ def define_tables(meta):
Column('id', String(36), primary_key=True, nullable=False),
Column('name', String(255)),
Column('qos_specs_id', String(36),
ForeignKey('quality_of_service_specs.id')),
ForeignKey('quality_of_service_specs.id'), index=True),
Column('is_public', Boolean),
Column('description', String(255)),
mysql_engine='InnoDB',
@ -327,7 +340,7 @@ def define_tables(meta):
Column('deleted', Boolean),
Column('id', Integer, primary_key=True, nullable=False),
Column('volume_id', String(36), ForeignKey('volumes.id'),
nullable=False),
nullable=False, index=True),
Column('key', String(255)),
Column('value', String(255)),
mysql_engine='InnoDB',
@ -344,7 +357,8 @@ def define_tables(meta):
Column('volume_type_id', String(36),
ForeignKey('volume_types.id',
name='volume_type_extra_specs_ibfk_1'),
nullable=False),
nullable=False,
index=True),
Column('key', String(255)),
Column('value', String(255)),
mysql_engine='InnoDB',
@ -394,6 +408,8 @@ def define_tables(meta):
Column('in_use', Integer(), nullable=False),
Column('reserved', Integer(), nullable=False),
Column('until_refresh', Integer(), nullable=True),
Index('quota_usage_project_resource_idx',
'project_id', 'resource'),
mysql_engine='InnoDB',
mysql_charset='utf8',
)
@ -410,15 +426,19 @@ def define_tables(meta):
Column('usage_id',
Integer(),
ForeignKey('quota_usages.id'),
nullable=True),
nullable=True,
index=True),
Column('project_id', String(255), index=True),
Column('resource', String(255)),
Column('delta', Integer(), nullable=False),
Column('expire', DateTime(timezone=False)),
Column('allocated_id', Integer, ForeignKey('quotas.id'),
nullable=True),
nullable=True,
index=True),
Index('reservations_deleted_expire_idx',
'deleted', 'expire'),
Index('reservations_deleted_uuid_idx',
'deleted', 'uuid'),
mysql_engine='InnoDB',
mysql_charset='utf8',
)
@ -431,9 +451,9 @@ def define_tables(meta):
Column('deleted_at', DateTime(timezone=False)),
Column('deleted', Boolean(create_constraint=True, name=None)),
Column('id', Integer(), primary_key=True, nullable=False),
Column('volume_id', String(36), ForeignKey('volumes.id')),
Column('volume_id', String(36), ForeignKey('volumes.id'), index=True),
Column('snapshot_id', String(36),
ForeignKey('snapshots.id')),
ForeignKey('snapshots.id'), index=True),
Column('key', String(255)),
Column('value', Text),
mysql_engine='InnoDB',
@ -468,6 +488,24 @@ def define_tables(meta):
Column('snapshot_id', String(36)),
Column('data_timestamp', DateTime),
Column('restore_volume_id', String(36)),
Column('encryption_key_id', String(36)),
mysql_engine='InnoDB',
mysql_charset='utf8'
)
backup_metadata = Table(
'backup_metadata', meta,
Column('created_at', DateTime(timezone=False)),
Column('updated_at', DateTime(timezone=False)),
Column('deleted_at', DateTime(timezone=False)),
Column('deleted', Boolean(), default=False),
Column('id', Integer, primary_key=True, nullable=False),
Column('backup_id', String(36),
ForeignKey('backups.id'),
nullable=False,
index=True),
Column('key', String(255)),
Column('value', String(255)),
mysql_engine='InnoDB',
mysql_charset='utf8'
)
@ -480,11 +518,12 @@ def define_tables(meta):
Column('deleted', Boolean),
Column('id', String(36), primary_key=True, nullable=False),
Column('volume_id', String(36), ForeignKey('volumes.id'),
nullable=False),
nullable=False, index=True),
Column('display_name', String(255)),
Column('salt', String(255)),
Column('crypt_hash', String(255)),
Column('expires_at', DateTime(timezone=False)),
Column('no_snapshots', Boolean, default=False),
mysql_engine='InnoDB',
mysql_charset='utf8'
)
@ -526,7 +565,7 @@ def define_tables(meta):
Column('deleted', Boolean),
Column('id', Integer, primary_key=True, nullable=False),
Column('volume_id', String(36), ForeignKey('volumes.id'),
nullable=False),
nullable=False, index=True),
Column('key', String(255)),
Column('value', String(255)),
mysql_engine='InnoDB',
@ -564,7 +603,7 @@ def define_tables(meta):
messages = Table(
'messages', meta,
Column('id', String(36), primary_key=True, nullable=False),
Column('project_id', String(36), nullable=False),
Column('project_id', String(255), nullable=False),
Column('request_id', String(255)),
Column('resource_type', String(36)),
Column('resource_uuid', String(255), nullable=True),
@ -574,7 +613,9 @@ def define_tables(meta):
Column('updated_at', DateTime(timezone=False)),
Column('deleted_at', DateTime(timezone=False)),
Column('deleted', Boolean),
Column('expires_at', DateTime(timezone=False)),
Column('expires_at', DateTime(timezone=False), index=True),
Column('detail_id', String(10), nullable=True),
Column('action_id', String(10), nullable=True),
mysql_engine='InnoDB',
mysql_charset='utf8'
)
@ -617,7 +658,7 @@ def define_tables(meta):
Column('resource_id', String(36), nullable=False),
Column('status', String(255), nullable=False),
Column('service_id', Integer, ForeignKey('services.id'),
nullable=True),
nullable=True, index=True),
Column('race_preventer', Integer, nullable=False, default=0,
server_default=text('0')),
UniqueConstraint('resource_type', 'resource_id'),
@ -646,7 +687,8 @@ def define_tables(meta):
Column('value', String(255)),
Column('group_type_id', String(36),
ForeignKey('group_types.id'),
nullable=False),
nullable=False,
index=True),
Column('created_at', DateTime(timezone=False)),
Column('updated_at', DateTime(timezone=False)),
Column('deleted_at', DateTime(timezone=False)),
@ -678,9 +720,11 @@ def define_tables(meta):
Column('deleted', Boolean),
Column('id', Integer, primary_key=True, nullable=False),
Column('volume_type_id', String(36), ForeignKey('volume_types.id'),
nullable=False),
nullable=False,
index=True),
Column('group_id', String(36),
ForeignKey('groups.id'), nullable=False),
ForeignKey('groups.id'), nullable=False,
index=True),
mysql_engine='InnoDB',
mysql_charset='utf8',
)
@ -689,6 +733,7 @@ def define_tables(meta):
cgsnapshots,
groups,
group_snapshots,
services,
volumes,
volume_attachment,
attachment_specs,
@ -698,7 +743,6 @@ def define_tables(meta):
volume_types,
volume_type_projects,
quotas,
services,
volume_metadata,
volume_type_extra_specs,
quota_classes,
@ -706,6 +750,7 @@ def define_tables(meta):
reservations,
volume_glance_metadata,
backups,
backup_metadata,
transfers,
encryption,
volume_admin_metadata,
@ -751,6 +796,7 @@ def upgrade(migrate_engine):
"reservations",
"volume_glance_metadata",
"backups",
"backup_metadata",
"transfers",
"encryption",
"volume_admin_metadata",

View File

@ -107,9 +107,6 @@ class MigrationsMixin(test_migrations.WalkVersionsMixin):
# manner is provided in Cinder's developer documentation.
# Reviewers: DO NOT ALLOW THINGS TO BE ADDED HERE WITHOUT CARE
exceptions = [
# NOTE : 104 modifies size of messages.project_id to 255.
# This should be safe according to documentation.
104,
# NOTE(brinzhang): 127 changes size of quota_usage.resource
# to 300. This should be safe for the 'quota_usage' db table,
# because of the 255 is the length limit of volume_type_name,
@ -132,20 +129,6 @@ class MigrationsMixin(test_migrations.WalkVersionsMixin):
self.assertIsInstance(columns.deleted_at.type, self.TIME_TYPE)
self.assertIsInstance(columns.deleted.type, self.BOOL_TYPE)
def _check_098(self, engine, data):
self.assertTrue(engine.dialect.has_table(engine.connect(),
"messages"))
ids = self.get_indexed_columns(engine, 'messages')
self.assertTrue('expires_at' in ids)
def _check_099(self, engine, data):
self.assertTrue(engine.dialect.has_table(engine.connect(),
"volume_attachment"))
attachment = db_utils.get_table(engine, 'volume_attachment')
self.assertIsInstance(attachment.c.connection_info.type,
self.TEXT_TYPE)
def get_table_names(self, engine):
inspector = reflection.Inspector.from_engine(engine)
return inspector.get_table_names()
@ -183,159 +166,6 @@ class MigrationsMixin(test_migrations.WalkVersionsMixin):
self.assertSetEqual(set(), non_indexed_foreign_keys)
def _pre_upgrade_101(self, engine):
"""Add data to test the SQL migration."""
types_table = db_utils.get_table(engine, 'volume_types')
for i in range(1, 5):
types_table.insert().execute({'id': str(i)})
specs_table = db_utils.get_table(engine, 'volume_type_extra_specs')
specs = [
{'volume_type_id': '1', 'key': 'key', 'value': '<is> False'},
{'volume_type_id': '2', 'key': 'replication_enabled',
'value': '<is> False'},
{'volume_type_id': '3', 'key': 'replication_enabled',
'value': '<is> True', 'deleted': True},
{'volume_type_id': '3', 'key': 'key', 'value': '<is> True'},
{'volume_type_id': '4', 'key': 'replication_enabled',
'value': '<is> True'},
{'volume_type_id': '4', 'key': 'key', 'value': '<is> True'},
]
for spec in specs:
specs_table.insert().execute(spec)
volumes_table = db_utils.get_table(engine, 'volumes')
volumes = [
{'id': '1', 'replication_status': 'disabled',
'volume_type_id': None},
{'id': '2', 'replication_status': 'disabled',
'volume_type_id': ''},
{'id': '3', 'replication_status': 'disabled',
'volume_type_id': '1'},
{'id': '4', 'replication_status': 'disabled',
'volume_type_id': '2'},
{'id': '5', 'replication_status': 'disabled',
'volume_type_id': '2'},
{'id': '6', 'replication_status': 'disabled',
'volume_type_id': '3'},
{'id': '7', 'replication_status': 'error', 'volume_type_id': '4'},
{'id': '8', 'deleted': True, 'replication_status': 'disabled',
'volume_type_id': '4'},
{'id': '9', 'replication_status': 'disabled', 'deleted': None,
'volume_type_id': '4'},
{'id': '10', 'replication_status': 'disabled', 'deleted': False,
'volume_type_id': '4'},
]
for volume in volumes:
volumes_table.insert().execute(volume)
# Only the last volume should be changed to enabled
expected = {v['id']: v['replication_status'] for v in volumes}
expected['9'] = 'enabled'
expected['10'] = 'enabled'
return expected
def _check_101(self, engine, data):
# Get existing volumes after the migration
volumes_table = db_utils.get_table(engine, 'volumes')
volumes = volumes_table.select().execute()
# Check that the replication_status is the one we expect according to
# _pre_upgrade_098
for volume in volumes:
self.assertEqual(data[volume.id], volume.replication_status,
'id %s' % volume.id)
def _check_102(self, engine, data):
"""Test adding replication_status to groups table."""
groups = db_utils.get_table(engine, 'groups')
self.assertIsInstance(groups.c.replication_status.type,
self.VARCHAR_TYPE)
def _check_103(self, engine, data):
self.assertTrue(engine.dialect.has_table(engine.connect(),
"messages"))
attachment = db_utils.get_table(engine, 'messages')
self.assertIsInstance(attachment.c.detail_id.type,
self.VARCHAR_TYPE)
self.assertIsInstance(attachment.c.action_id.type,
self.VARCHAR_TYPE)
def _check_104(self, engine, data):
messages = db_utils.get_table(engine, 'messages')
self.assertEqual(255, messages.c.project_id.type.length)
def _check_105(self, engine, data):
self.assertTrue(engine.dialect.has_table(engine.connect(),
"backup_metadata"))
backup_metadata = db_utils.get_table(engine, 'backup_metadata')
self.assertIsInstance(backup_metadata.c.created_at.type,
self.TIME_TYPE)
self.assertIsInstance(backup_metadata.c.updated_at.type,
self.TIME_TYPE)
self.assertIsInstance(backup_metadata.c.deleted_at.type,
self.TIME_TYPE)
self.assertIsInstance(backup_metadata.c.deleted.type,
self.BOOL_TYPE)
self.assertIsInstance(backup_metadata.c.id.type,
self.INTEGER_TYPE)
self.assertIsInstance(backup_metadata.c.key.type,
self.VARCHAR_TYPE)
self.assertIsInstance(backup_metadata.c.value.type,
self.VARCHAR_TYPE)
self.assertIsInstance(backup_metadata.c.backup_id.type,
self.VARCHAR_TYPE)
f_keys = self.get_foreign_key_columns(engine, 'backup_metadata')
self.assertEqual({'backup_id'}, f_keys)
def _check_111(self, engine, data):
self.assertTrue(db_utils.index_exists_on_columns(
engine, 'quota_usages', ['project_id', 'resource']))
def _check_112(self, engine, data):
services = db_utils.get_table(engine, 'services')
self.assertIsInstance(services.c.uuid.type,
self.VARCHAR_TYPE)
def _check_113(self, engine, data):
"""Test that adding reservations index works correctly."""
reservations = db_utils.get_table(engine, 'reservations')
index_columns = []
for idx in reservations.indexes:
if idx.name == 'reservations_deleted_uuid_idx':
index_columns = idx.columns.keys()
break
self.assertEqual(sorted(['deleted', 'uuid']),
sorted(index_columns))
def _check_114(self, engine, data):
volumes = db_utils.get_table(engine, 'volumes')
self.assertIsInstance(volumes.c.service_uuid.type,
self.VARCHAR_TYPE)
index_columns = []
for idx in volumes.indexes:
if idx.name == 'volumes_service_uuid_idx':
index_columns = idx.columns.keys()
break
self.assertEqual(sorted(['deleted', 'service_uuid']),
sorted(index_columns))
def _check_115(self, engine, data):
volumes = db_utils.get_table(engine, 'volumes')
self.assertIsInstance(volumes.c.shared_targets.type,
self.BOOL_TYPE)
def _check_116(self, engine, data):
volume_attachment = db_utils.get_table(engine, 'volume_attachment')
self.assertIn('connector', volume_attachment.c)
def _check_123(self, engine, data):
volume_transfer = db_utils.get_table(engine, 'transfers')
self.assertIn('no_snapshots', volume_transfer.c)
def _check_127(self, engine, data):
quota_usage_resource = db_utils.get_table(engine, 'quota_usages')
self.assertIn('resource', quota_usage_resource.c)

View File

@ -0,0 +1,6 @@
---
upgrade:
- |
The Cinder database can now only be upgraded with changes since the Queens
release. In order to upgrade from a version prior to that, you must now
upgrade to at least Queens first.