From 0162a42970b833c2d5d0802ff4c55f65fa253ee2 Mon Sep 17 00:00:00 2001 From: Brian Waldon Date: Wed, 12 Oct 2011 16:28:24 -0400 Subject: Convert instancetype.flavorid to string Fixes bug 861666. This also removes some direct database access in favor of using nova.compute.instance_types throughout the code. Change-Id: I572cc19454fa76f435f5672d3d6e7ed55c8817da --- nova/db/sqlalchemy/api.py | 9 +- .../versions/055_convert_flavor_id_to_str.py | 117 +++++++++++++++++++++ nova/db/sqlalchemy/models.py | 2 +- 3 files changed, 120 insertions(+), 8 deletions(-) create mode 100644 nova/db/sqlalchemy/migrate_repo/versions/055_convert_flavor_id_to_str.py (limited to 'nova/db') diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index cb049652b..370ac3001 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -3368,7 +3368,7 @@ def instance_type_get(context, id): first() if not inst_type: - raise exception.InstanceTypeNotFound(instance_type=id) + raise exception.InstanceTypeNotFound(instance_type_id=id) else: return _dict_with_extra_specs(inst_type) @@ -3388,13 +3388,8 @@ def instance_type_get_by_name(context, name): @require_context -def instance_type_get_by_flavor_id(context, id): +def instance_type_get_by_flavor_id(context, flavor_id): """Returns a dict describing specific flavor_id""" - try: - flavor_id = int(id) - except ValueError: - raise exception.FlavorNotFound(flavor_id=id) - session = get_session() inst_type = session.query(models.InstanceTypes).\ options(joinedload('extra_specs')).\ diff --git a/nova/db/sqlalchemy/migrate_repo/versions/055_convert_flavor_id_to_str.py b/nova/db/sqlalchemy/migrate_repo/versions/055_convert_flavor_id_to_str.py new file mode 100644 index 000000000..082b7c455 --- /dev/null +++ b/nova/db/sqlalchemy/migrate_repo/versions/055_convert_flavor_id_to_str.py @@ -0,0 +1,117 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2011 OpenStack LLC. +# 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. + +import migrate +import migrate.changeset +import sqlalchemy + +from nova import log as logging + + +LOG = logging.getLogger('nova.db.sqlalchemy.migrate_repo.versions') + +meta = sqlalchemy.MetaData() + + +def _get_table(): + return sqlalchemy.Table('instance_types', meta, autoload=True) + + +def upgrade(migrate_engine): + meta.bind = migrate_engine + instance_types = _get_table() + + string_column = sqlalchemy.Column('flavorid_str', sqlalchemy.String(255)) + + string_column.create(instance_types) + + try: + # NOTE(bcwaldon): This catches a bug with python-migrate + # failing to add the unique constraint + try: + migrate.UniqueConstraint(string_column).create() + except migrate.changeset.NotSupportedError: + LOG.error("Failed to add unique constraint on flavorid") + pass + + # NOTE(bcwaldon): this is a hack to preserve uniqueness constraint + # on existing 'name' column + try: + migrate.UniqueConstraint(instance_types.c.name).create() + except Exception: + pass + + integer_column = instance_types.c.flavorid + + instance_type_rows = list(instance_types.select().execute()) + for instance_type in instance_type_rows: + flavorid_int = instance_type.flavorid + instance_types.update()\ + .where(integer_column == flavorid_int)\ + .values(flavorid_str=str(flavorid_int))\ + .execute() + except Exception: + string_column.drop() + raise + + integer_column.alter(name='flavorid_int') + string_column.alter(name='flavorid') + integer_column.drop() + + +def downgrade(migrate_engine): + meta.bind = migrate_engine + instance_types = _get_table() + + integer_column = sqlalchemy.Column('flavorid_int', + sqlalchemy.Integer()) + + integer_column.create(instance_types) + + try: + # NOTE(bcwaldon): This catches a bug with python-migrate + # failing to add the unique constraint + try: + migrate.UniqueConstraint(integer_column).create() + except migrate.changeset.NotSupportedError: + LOG.info("Failed to add unique constraint on flavorid") + pass + + string_column = instance_types.c.flavorid + + instance_types_rows = list(instance_types.select().execute()) + for instance_type in instance_types_rows: + flavorid_str = instance_type.flavorid + try: + flavorid_int = int(instance_type.flavorid) + except ValueError: + msg = _('Could not cast flavorid to integer: %s. ' + 'Set flavorid to an integer-like string to downgrade.') + LOG.error(msg % instance_type.flavorid) + raise + + instance_types.update()\ + .where(string_column == flavorid_str)\ + .values(flavorid_int=flavorid_int)\ + .execute() + except Exception: + integer_column.drop() + raise + + string_column.alter(name='flavorid_str') + integer_column.alter(name='flavorid') + string_column.drop() diff --git a/nova/db/sqlalchemy/models.py b/nova/db/sqlalchemy/models.py index 6240fcff0..e493c78d5 100644 --- a/nova/db/sqlalchemy/models.py +++ b/nova/db/sqlalchemy/models.py @@ -303,7 +303,7 @@ class InstanceTypes(BASE, NovaBase): memory_mb = Column(Integer) vcpus = Column(Integer) local_gb = Column(Integer) - flavorid = Column(Integer, unique=True) + flavorid = Column(String(255), unique=True) swap = Column(Integer, nullable=False, default=0) rxtx_quota = Column(Integer, nullable=False, default=0) rxtx_cap = Column(Integer, nullable=False, default=0) -- cgit