apidb: Compact Ocata database migrations
Specific changes include: - Add 'resource_classes' table (026) - Add 'quota_classes', 'quota_usages', 'quotas', 'project_user_quotas', 'reservations' and 'resource_classes' tables (027) - Alter type of 'instance' column of 'build_requests' table to 'MediumText' (028) - Add 'placement_aggregates' table (029) Note that migration 030 included a check to ensure cell mappings were created when upgrading existing deployments. Since users will now be required to upgrade to at Ocata before running migrations, this is no longer necessary. The check was never executed for new deployments, as noted in the migration itself: NOTE(danms): We need to be careful here if this is a new installation, which can't possibly have any mappings. Check to see if any flavors are defined to determine if we are upgrading an existing system. If not, then don't obsess over the lack of mappings. Change-Id: Ibf82b5e8f46b89f8c7dcdc1925bf48d581cdc3f6 Signed-off-by: Stephen Finucane <stephenfin@redhat.com>
This commit is contained in:
parent
302f2bc4f7
commit
743693c740
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -1,36 +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 Integer
|
||||
from sqlalchemy import MetaData
|
||||
from sqlalchemy import String
|
||||
from sqlalchemy import Table
|
||||
|
||||
|
||||
def upgrade(migrate_engine):
|
||||
meta = MetaData()
|
||||
meta.bind = migrate_engine
|
||||
|
||||
resource_classes = Table('resource_classes', meta,
|
||||
Column('id', Integer, primary_key=True, nullable=False),
|
||||
Column('name', String(length=255), nullable=False),
|
||||
Column('created_at', DateTime),
|
||||
Column('updated_at', DateTime),
|
||||
UniqueConstraint('name', name='uniq_resource_classes0name'),
|
||||
mysql_engine='InnoDB',
|
||||
mysql_charset='latin1'
|
||||
)
|
||||
|
||||
resource_classes.create(checkfirst=True)
|
|
@ -1,124 +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 quotas"""
|
||||
|
||||
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
|
||||
|
||||
quota_classes = Table('quota_classes', meta,
|
||||
Column('created_at', DateTime),
|
||||
Column('updated_at', DateTime),
|
||||
Column('id', Integer, primary_key=True, nullable=False),
|
||||
Column('class_name', String(length=255)),
|
||||
Column('resource', String(length=255)),
|
||||
Column('hard_limit', Integer),
|
||||
Index('quota_classes_class_name_idx', 'class_name'),
|
||||
mysql_engine='InnoDB',
|
||||
mysql_charset='utf8'
|
||||
)
|
||||
|
||||
quota_classes.create(checkfirst=True)
|
||||
|
||||
quota_usages = Table('quota_usages', meta,
|
||||
Column('created_at', DateTime),
|
||||
Column('updated_at', DateTime),
|
||||
Column('id', Integer, primary_key=True, nullable=False),
|
||||
Column('project_id', String(length=255)),
|
||||
Column('resource', String(length=255), nullable=False),
|
||||
Column('in_use', Integer, nullable=False),
|
||||
Column('reserved', Integer, nullable=False),
|
||||
Column('until_refresh', Integer),
|
||||
Column('user_id', String(length=255)),
|
||||
Index('quota_usages_project_id_idx', 'project_id'),
|
||||
Index('quota_usages_user_id_idx', 'user_id'),
|
||||
mysql_engine='InnoDB',
|
||||
mysql_charset='utf8'
|
||||
)
|
||||
|
||||
quota_usages.create(checkfirst=True)
|
||||
|
||||
quotas = Table('quotas', meta,
|
||||
Column('id', Integer, primary_key=True, nullable=False),
|
||||
Column('created_at', DateTime),
|
||||
Column('updated_at', DateTime),
|
||||
Column('project_id', String(length=255)),
|
||||
Column('resource', String(length=255), nullable=False),
|
||||
Column('hard_limit', Integer),
|
||||
UniqueConstraint('project_id', 'resource',
|
||||
name='uniq_quotas0project_id0resource'),
|
||||
mysql_engine='InnoDB',
|
||||
mysql_charset='utf8'
|
||||
)
|
||||
|
||||
quotas.create(checkfirst=True)
|
||||
|
||||
uniq_name = "uniq_project_user_quotas0user_id0project_id0resource"
|
||||
project_user_quotas = Table('project_user_quotas', meta,
|
||||
Column('id', Integer, primary_key=True,
|
||||
nullable=False),
|
||||
Column('created_at', DateTime),
|
||||
Column('updated_at', DateTime),
|
||||
Column('user_id',
|
||||
String(length=255),
|
||||
nullable=False),
|
||||
Column('project_id',
|
||||
String(length=255),
|
||||
nullable=False),
|
||||
Column('resource',
|
||||
String(length=255),
|
||||
nullable=False),
|
||||
Column('hard_limit', Integer, nullable=True),
|
||||
UniqueConstraint('user_id', 'project_id', 'resource',
|
||||
name=uniq_name),
|
||||
Index('project_user_quotas_project_id_idx',
|
||||
'project_id'),
|
||||
Index('project_user_quotas_user_id_idx',
|
||||
'user_id'),
|
||||
mysql_engine='InnoDB',
|
||||
mysql_charset='utf8',
|
||||
)
|
||||
|
||||
project_user_quotas.create(checkfirst=True)
|
||||
|
||||
reservations = Table('reservations', 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('usage_id', Integer, ForeignKey('quota_usages.id'),
|
||||
nullable=False),
|
||||
Column('project_id', String(length=255)),
|
||||
Column('resource', String(length=255)),
|
||||
Column('delta', Integer, nullable=False),
|
||||
Column('expire', DateTime),
|
||||
Column('user_id', String(length=255)),
|
||||
Index('reservations_project_id_idx', 'project_id'),
|
||||
Index('reservations_uuid_idx', 'uuid'),
|
||||
Index('reservations_expire_idx', 'expire'),
|
||||
Index('reservations_user_id_idx', 'user_id'),
|
||||
mysql_engine='InnoDB',
|
||||
mysql_charset='utf8'
|
||||
)
|
||||
|
||||
reservations.create(checkfirst=True)
|
|
@ -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.instance.alter(type=api_models.MediumText())
|
|
@ -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.
|
||||
"""API Database migrations for placement_aggregates"""
|
||||
|
||||
from migrate import UniqueConstraint
|
||||
from sqlalchemy import Column
|
||||
from sqlalchemy import DateTime
|
||||
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
|
||||
|
||||
placement_aggregates = Table('placement_aggregates', meta,
|
||||
Column('created_at', DateTime),
|
||||
Column('updated_at', DateTime),
|
||||
Column('id', Integer, primary_key=True, nullable=False),
|
||||
Column('uuid', String(length=36), index=True),
|
||||
UniqueConstraint('uuid', name='uniq_placement_aggregates0uuid'),
|
||||
mysql_engine='InnoDB',
|
||||
mysql_charset='latin1'
|
||||
)
|
||||
|
||||
placement_aggregates.create(checkfirst=True)
|
|
@ -174,7 +174,7 @@ def upgrade(migrate_engine):
|
|||
'locked_by',
|
||||
Enum('owner', 'admin', name='build_requests0locked_by')),
|
||||
Column('instance_uuid', String(length=36)),
|
||||
Column('instance', Text()),
|
||||
Column('instance', MediumText()),
|
||||
Column('block_device_mappings', MediumText()),
|
||||
UniqueConstraint(
|
||||
'instance_uuid', name='uniq_build_requests0instance_uuid'),
|
||||
|
@ -201,6 +201,16 @@ def upgrade(migrate_engine):
|
|||
mysql_charset='utf8'
|
||||
)
|
||||
|
||||
resource_classes = Table('resource_classes', meta,
|
||||
Column('id', Integer, primary_key=True, nullable=False),
|
||||
Column('name', String(length=255), nullable=False),
|
||||
Column('created_at', DateTime),
|
||||
Column('updated_at', DateTime),
|
||||
UniqueConstraint('name', name='uniq_resource_classes0name'),
|
||||
mysql_engine='InnoDB',
|
||||
mysql_charset='latin1'
|
||||
)
|
||||
|
||||
nameargs = {}
|
||||
if migrate_engine.name == 'mysql':
|
||||
nameargs['collation'] = 'utf8_bin'
|
||||
|
@ -281,6 +291,16 @@ def upgrade(migrate_engine):
|
|||
mysql_charset='latin1'
|
||||
)
|
||||
|
||||
placement_aggregates = Table('placement_aggregates', meta,
|
||||
Column('created_at', DateTime),
|
||||
Column('updated_at', DateTime),
|
||||
Column('id', Integer, primary_key=True, nullable=False),
|
||||
Column('uuid', String(length=36), index=True),
|
||||
UniqueConstraint('uuid', name='uniq_placement_aggregates0uuid'),
|
||||
mysql_engine='InnoDB',
|
||||
mysql_charset='latin1'
|
||||
)
|
||||
|
||||
aggregates = Table('aggregates', meta,
|
||||
Column('created_at', DateTime),
|
||||
Column('updated_at', DateTime),
|
||||
|
@ -365,6 +385,87 @@ def upgrade(migrate_engine):
|
|||
mysql_charset='utf8',
|
||||
)
|
||||
|
||||
quota_classes = Table('quota_classes', meta,
|
||||
Column('created_at', DateTime),
|
||||
Column('updated_at', DateTime),
|
||||
Column('id', Integer, primary_key=True, nullable=False),
|
||||
Column('class_name', String(length=255)),
|
||||
Column('resource', String(length=255)),
|
||||
Column('hard_limit', Integer),
|
||||
Index('quota_classes_class_name_idx', 'class_name'),
|
||||
mysql_engine='InnoDB',
|
||||
mysql_charset='utf8',
|
||||
)
|
||||
|
||||
quota_usages = Table('quota_usages', meta,
|
||||
Column('created_at', DateTime),
|
||||
Column('updated_at', DateTime),
|
||||
Column('id', Integer, primary_key=True, nullable=False),
|
||||
Column('project_id', String(length=255)),
|
||||
Column('resource', String(length=255), nullable=False),
|
||||
Column('in_use', Integer, nullable=False),
|
||||
Column('reserved', Integer, nullable=False),
|
||||
Column('until_refresh', Integer),
|
||||
Column('user_id', String(length=255)),
|
||||
Index('quota_usages_project_id_idx', 'project_id'),
|
||||
Index('quota_usages_user_id_idx', 'user_id'),
|
||||
mysql_engine='InnoDB',
|
||||
mysql_charset='utf8',
|
||||
)
|
||||
|
||||
quotas = Table('quotas', meta,
|
||||
Column('id', Integer, primary_key=True, nullable=False),
|
||||
Column('created_at', DateTime),
|
||||
Column('updated_at', DateTime),
|
||||
Column('project_id', String(length=255)),
|
||||
Column('resource', String(length=255), nullable=False),
|
||||
Column('hard_limit', Integer),
|
||||
UniqueConstraint(
|
||||
'project_id', 'resource', name='uniq_quotas0project_id0resource'),
|
||||
mysql_engine='InnoDB',
|
||||
mysql_charset='utf8',
|
||||
)
|
||||
|
||||
project_user_quotas = Table('project_user_quotas', meta,
|
||||
Column('id', Integer, primary_key=True, nullable=False),
|
||||
Column('created_at', DateTime),
|
||||
Column('updated_at', DateTime),
|
||||
Column('user_id', String(length=255), nullable=False),
|
||||
Column('project_id', String(length=255), nullable=False),
|
||||
Column('resource', String(length=255), nullable=False),
|
||||
Column('hard_limit', Integer, nullable=True),
|
||||
UniqueConstraint(
|
||||
'user_id', 'project_id', 'resource',
|
||||
name='uniq_project_user_quotas0user_id0project_id0resource'),
|
||||
Index(
|
||||
'project_user_quotas_project_id_idx', 'project_id'),
|
||||
Index(
|
||||
'project_user_quotas_user_id_idx', 'user_id'),
|
||||
mysql_engine='InnoDB',
|
||||
mysql_charset='utf8',
|
||||
)
|
||||
|
||||
reservations = Table('reservations', 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(
|
||||
'usage_id', Integer, ForeignKey('quota_usages.id'),
|
||||
nullable=False),
|
||||
Column('project_id', String(length=255)),
|
||||
Column('resource', String(length=255)),
|
||||
Column('delta', Integer, nullable=False),
|
||||
Column('expire', DateTime),
|
||||
Column('user_id', String(length=255)),
|
||||
Index('reservations_project_id_idx', 'project_id'),
|
||||
Index('reservations_uuid_idx', 'uuid'),
|
||||
Index('reservations_expire_idx', 'expire'),
|
||||
Index('reservations_user_id_idx', 'user_id'),
|
||||
mysql_engine='InnoDB',
|
||||
mysql_charset='utf8',
|
||||
)
|
||||
|
||||
tables = [
|
||||
cell_mappings,
|
||||
host_mappings,
|
||||
|
@ -375,16 +476,23 @@ def upgrade(migrate_engine):
|
|||
request_specs,
|
||||
build_requests,
|
||||
keypairs,
|
||||
resource_classes,
|
||||
resource_providers,
|
||||
inventories,
|
||||
allocations,
|
||||
resource_provider_aggregates,
|
||||
placement_aggregates,
|
||||
aggregates,
|
||||
aggregate_hosts,
|
||||
aggregate_metadata,
|
||||
groups,
|
||||
group_policy,
|
||||
group_member,
|
||||
quota_classes,
|
||||
quota_usages,
|
||||
quotas,
|
||||
project_user_quotas,
|
||||
reservations,
|
||||
]
|
||||
for table in tables:
|
||||
table.create(checkfirst=True)
|
|
@ -1,59 +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_log import log as logging
|
||||
from sqlalchemy import MetaData, Table, func, select
|
||||
|
||||
from nova import exception
|
||||
from nova.i18n import _
|
||||
from nova import objects
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def upgrade(migrate_engine):
|
||||
meta = MetaData()
|
||||
meta.bind = migrate_engine
|
||||
|
||||
flavors = Table('flavors', meta, autoload=True)
|
||||
count = select([func.count()]).select_from(flavors).scalar()
|
||||
if count == 0:
|
||||
# NOTE(danms): We need to be careful here if this is a new
|
||||
# installation, which can't possibly have any mappings. Check
|
||||
# to see if any flavors are defined to determine if we are
|
||||
# upgrading an existing system. If not, then don't obsess over
|
||||
# the lack of mappings
|
||||
return
|
||||
|
||||
cell_mappings = Table('cell_mappings', meta, autoload=True)
|
||||
count = select([func.count()]).select_from(cell_mappings).scalar()
|
||||
# Two mappings are required at a minimum, cell0 and your first cell
|
||||
if count < 2:
|
||||
msg = _('Cell mappings are not created, but required for Ocata. '
|
||||
'Please run nova-manage cell_v2 simple_cell_setup before '
|
||||
'continuing.')
|
||||
raise exception.ValidationError(detail=msg)
|
||||
|
||||
count = select([func.count()]).select_from(cell_mappings).where(
|
||||
cell_mappings.c.uuid == objects.CellMapping.CELL0_UUID).scalar()
|
||||
if count != 1:
|
||||
msg = _('A mapping for Cell0 was not found, but is required for '
|
||||
'Ocata. Please run nova-manage cell_v2 simple_cell_setup '
|
||||
'before continuing.')
|
||||
raise exception.ValidationError(detail=msg)
|
||||
|
||||
host_mappings = Table('host_mappings', meta, autoload=True)
|
||||
count = select([func.count()]).select_from(host_mappings).scalar()
|
||||
if count == 0:
|
||||
LOG.warning('No host mappings were found, but are required for Ocata. '
|
||||
'Please run nova-manage cell_v2 simple_cell_setup before '
|
||||
'continuing.')
|
|
@ -30,7 +30,7 @@ from nova.i18n import _
|
|||
|
||||
INIT_VERSION = {}
|
||||
INIT_VERSION['main'] = 401
|
||||
INIT_VERSION['api'] = 19
|
||||
INIT_VERSION['api'] = 29
|
||||
_REPOSITORY = {}
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
|
|
@ -172,7 +172,6 @@ class NovaAPIMigrationsWalk(test_migrations.WalkVersionsMixin):
|
|||
return self.engine
|
||||
|
||||
def _skippable_migrations(self):
|
||||
newton_placeholders = list(range(21, 26))
|
||||
ocata_placeholders = list(range(31, 41))
|
||||
pike_placeholders = list(range(45, 50))
|
||||
queens_placeholders = list(range(53, 58))
|
||||
|
@ -183,10 +182,8 @@ class NovaAPIMigrationsWalk(test_migrations.WalkVersionsMixin):
|
|||
victoria_placeholders = list(range(78, 83))
|
||||
special_cases = [
|
||||
self.INIT_VERSION + 1, # initial change
|
||||
30, # Enforcement migration, no changes to test
|
||||
]
|
||||
return (newton_placeholders +
|
||||
ocata_placeholders +
|
||||
return (ocata_placeholders +
|
||||
pike_placeholders +
|
||||
queens_placeholders +
|
||||
stein_placeholders +
|
||||
|
@ -226,119 +223,6 @@ class NovaAPIMigrationsWalk(test_migrations.WalkVersionsMixin):
|
|||
self.assertRaises(sqlalchemy.exc.NoSuchTableError,
|
||||
db_utils.get_table, engine, table_name)
|
||||
|
||||
def _check_026(self, engine, data):
|
||||
self.assertColumnExists(engine, 'resource_classes', 'id')
|
||||
self.assertColumnExists(engine, 'resource_classes', 'name')
|
||||
|
||||
def _check_027(self, engine, data):
|
||||
# quota_classes
|
||||
for column in ['created_at',
|
||||
'updated_at',
|
||||
'id',
|
||||
'class_name',
|
||||
'resource',
|
||||
'hard_limit']:
|
||||
self.assertColumnExists(engine, 'quota_classes', column)
|
||||
|
||||
self.assertIndexExists(engine, 'quota_classes',
|
||||
'quota_classes_class_name_idx')
|
||||
|
||||
# quota_usages
|
||||
for column in ['created_at',
|
||||
'updated_at',
|
||||
'id',
|
||||
'project_id',
|
||||
'resource',
|
||||
'in_use',
|
||||
'reserved',
|
||||
'until_refresh',
|
||||
'user_id']:
|
||||
self.assertColumnExists(engine, 'quota_usages', column)
|
||||
|
||||
self.assertIndexExists(engine, 'quota_usages',
|
||||
'quota_usages_project_id_idx')
|
||||
self.assertIndexExists(engine, 'quota_usages',
|
||||
'quota_usages_user_id_idx')
|
||||
|
||||
# quotas
|
||||
for column in ['created_at',
|
||||
'updated_at',
|
||||
'id',
|
||||
'project_id',
|
||||
'resource',
|
||||
'hard_limit']:
|
||||
self.assertColumnExists(engine, 'quotas', column)
|
||||
|
||||
self.assertUniqueConstraintExists(engine, 'quotas',
|
||||
['project_id', 'resource'])
|
||||
|
||||
# project_user_quotas
|
||||
for column in ['created_at',
|
||||
'updated_at',
|
||||
'id',
|
||||
'user_id',
|
||||
'project_id',
|
||||
'resource',
|
||||
'hard_limit']:
|
||||
self.assertColumnExists(engine, 'project_user_quotas', column)
|
||||
|
||||
self.assertUniqueConstraintExists(engine, 'project_user_quotas',
|
||||
['user_id', 'project_id', 'resource'])
|
||||
self.assertIndexExists(engine, 'project_user_quotas',
|
||||
'project_user_quotas_project_id_idx')
|
||||
self.assertIndexExists(engine, 'project_user_quotas',
|
||||
'project_user_quotas_user_id_idx')
|
||||
|
||||
# reservations
|
||||
for column in ['created_at',
|
||||
'updated_at',
|
||||
'id',
|
||||
'uuid',
|
||||
'usage_id',
|
||||
'project_id',
|
||||
'resource',
|
||||
'delta',
|
||||
'expire',
|
||||
'user_id']:
|
||||
self.assertColumnExists(engine, 'reservations', column)
|
||||
|
||||
self.assertIndexExists(engine, 'reservations',
|
||||
'reservations_project_id_idx')
|
||||
self.assertIndexExists(engine, 'reservations',
|
||||
'reservations_uuid_idx')
|
||||
self.assertIndexExists(engine, 'reservations',
|
||||
'reservations_expire_idx')
|
||||
self.assertIndexExists(engine, 'reservations',
|
||||
'reservations_user_id_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('reservations')[0]
|
||||
self.assertEqual('quota_usages', fk['referred_table'])
|
||||
self.assertEqual(['id'], fk['referred_columns'])
|
||||
|
||||
def _pre_upgrade_028(self, engine):
|
||||
build_requests = db_utils.get_table(engine, 'build_requests')
|
||||
fake_build_req = {'id': 2021,
|
||||
'project_id': 'fake_proj_id',
|
||||
'instance': '{"uuid": "foo", "name": "bar"}'}
|
||||
build_requests.insert().execute(fake_build_req)
|
||||
|
||||
def _check_028(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 == 2021).execute().first()
|
||||
self.assertEqual('{"uuid": "foo", "name": "bar"}',
|
||||
fake_build_req.instance)
|
||||
|
||||
def _check_029(self, engine, data):
|
||||
for column in ['created_at', 'updated_at', 'id', 'uuid']:
|
||||
self.assertColumnExists(engine, 'placement_aggregates', column)
|
||||
|
||||
def _check_041(self, engine, data):
|
||||
self.assertColumnExists(engine, 'traits', 'id')
|
||||
self.assertUniqueConstraintExists(engine, 'traits', ['name'])
|
||||
|
|
|
@ -12,23 +12,15 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import importlib
|
||||
|
||||
from migrate import exceptions as versioning_exceptions
|
||||
from migrate import UniqueConstraint
|
||||
from migrate.versioning import api as versioning_api
|
||||
import mock
|
||||
from oslo_db.sqlalchemy import utils as db_utils
|
||||
from oslo_utils.fixture import uuidsentinel
|
||||
import sqlalchemy
|
||||
|
||||
from nova import context
|
||||
from nova.db.sqlalchemy import api as db_api
|
||||
from nova.db.sqlalchemy import migration
|
||||
from nova import exception
|
||||
from nova import objects
|
||||
from nova import test
|
||||
from nova.tests import fixtures as nova_fixtures
|
||||
|
||||
|
||||
class TestNullInstanceUuidScanDB(test.TestCase):
|
||||
|
@ -229,96 +221,3 @@ class TestGetEngine(test.NoDBTestCase):
|
|||
engine = migration.get_engine('api')
|
||||
self.assertEqual('api_engine', engine)
|
||||
mock_get_engine.assert_called_once_with()
|
||||
|
||||
|
||||
class TestNewtonCellsCheck(test.NoDBTestCase):
|
||||
USES_DB_SELF = True
|
||||
|
||||
def setUp(self):
|
||||
super(TestNewtonCellsCheck, self).setUp()
|
||||
self.useFixture(nova_fixtures.Database('api', 28))
|
||||
self.context = context.get_admin_context()
|
||||
self.migration = importlib.import_module(
|
||||
'nova.db.sqlalchemy.api_migrations.migrate_repo.versions.'
|
||||
'030_require_cell_setup')
|
||||
self.engine = db_api.get_api_engine()
|
||||
|
||||
def _flavor_me(self):
|
||||
# We can't use the Flavor object or model to create the flavor because
|
||||
# the model and object have the description field now but at this point
|
||||
# we have not run the migration schema to add the description column.
|
||||
flavors = db_utils.get_table(self.engine, 'flavors')
|
||||
values = dict(name='foo', memory_mb=123,
|
||||
vcpus=1, root_gb=1,
|
||||
flavorid='m1.foo', swap=0)
|
||||
flavors.insert().execute(values)
|
||||
|
||||
def _create_cell_mapping(self, **values):
|
||||
mappings = db_utils.get_table(self.engine, 'cell_mappings')
|
||||
return mappings.insert().execute(**values).inserted_primary_key[0]
|
||||
|
||||
def _create_host_mapping(self, **values):
|
||||
mappings = db_utils.get_table(self.engine, 'host_mappings')
|
||||
return mappings.insert().execute(**values).inserted_primary_key[0]
|
||||
|
||||
def test_upgrade_with_no_cell_mappings(self):
|
||||
self._flavor_me()
|
||||
self.assertRaisesRegex(exception.ValidationError,
|
||||
'Cell mappings',
|
||||
self.migration.upgrade, self.engine)
|
||||
|
||||
def test_upgrade_with_only_cell0(self):
|
||||
self._flavor_me()
|
||||
self._create_cell_mapping(uuid=objects.CellMapping.CELL0_UUID,
|
||||
name='cell0',
|
||||
transport_url='fake',
|
||||
database_connection='fake')
|
||||
self.assertRaisesRegex(exception.ValidationError,
|
||||
'Cell mappings',
|
||||
self.migration.upgrade, self.engine)
|
||||
|
||||
def test_upgrade_without_cell0(self):
|
||||
self._flavor_me()
|
||||
self._create_cell_mapping(uuid=uuidsentinel.cell1,
|
||||
name='cell1',
|
||||
transport_url='fake',
|
||||
database_connection='fake')
|
||||
self._create_cell_mapping(uuid=uuidsentinel.cell2,
|
||||
name='cell2',
|
||||
transport_url='fake',
|
||||
database_connection='fake')
|
||||
self.assertRaisesRegex(exception.ValidationError,
|
||||
'Cell0',
|
||||
self.migration.upgrade, self.engine)
|
||||
|
||||
def test_upgrade_with_no_host_mappings(self):
|
||||
self._flavor_me()
|
||||
self._create_cell_mapping(uuid=objects.CellMapping.CELL0_UUID,
|
||||
name='cell0',
|
||||
transport_url='fake',
|
||||
database_connection='fake')
|
||||
self._create_cell_mapping(uuid=uuidsentinel.cell1,
|
||||
name='cell1',
|
||||
transport_url='fake',
|
||||
database_connection='fake')
|
||||
|
||||
with mock.patch.object(self.migration, 'LOG') as log:
|
||||
self.migration.upgrade(self.engine)
|
||||
self.assertTrue(log.warning.called)
|
||||
|
||||
def test_upgrade_with_required_mappings(self):
|
||||
self._flavor_me()
|
||||
self._create_cell_mapping(uuid=objects.CellMapping.CELL0_UUID,
|
||||
name='cell0',
|
||||
transport_url='fake',
|
||||
database_connection='fake')
|
||||
cell1_id = self._create_cell_mapping(uuid=uuidsentinel.cell1,
|
||||
name='cell1',
|
||||
transport_url='fake',
|
||||
database_connection='fake')
|
||||
self._create_host_mapping(cell_id=cell1_id, host='foo')
|
||||
|
||||
self.migration.upgrade(self.engine)
|
||||
|
||||
def test_upgrade_new_deploy(self):
|
||||
self.migration.upgrade(self.engine)
|
||||
|
|
Loading…
Reference in New Issue