diff --git a/nova/db/sqlalchemy/api_migrations/migrate_repo/versions/052_request_specs_spec_mediumtext.py b/nova/db/sqlalchemy/api_migrations/migrate_repo/versions/052_request_specs_spec_mediumtext.py new file mode 100644 index 000000000000..e0eef79a022c --- /dev/null +++ b/nova/db/sqlalchemy/api_migrations/migrate_repo/versions/052_request_specs_spec_mediumtext.py @@ -0,0 +1,25 @@ +# 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 + + request_specs = Table('request_specs', meta, autoload=True) + if request_specs.c.spec.type != api_models.MediumText(): + request_specs.c.spec.alter(type=api_models.MediumText()) diff --git a/nova/db/sqlalchemy/api_models.py b/nova/db/sqlalchemy/api_models.py index 7e5e7b19f92d..ae043a316b3f 100644 --- a/nova/db/sqlalchemy/api_models.py +++ b/nova/db/sqlalchemy/api_models.py @@ -168,7 +168,7 @@ class RequestSpec(API_BASE): id = Column(Integer, primary_key=True) instance_uuid = Column(String(36), nullable=False) - spec = Column(Text, nullable=False) + spec = Column(MediumText(), nullable=False) class Flavors(API_BASE): diff --git a/nova/tests/functional/db/api/test_migrations.py b/nova/tests/functional/db/api/test_migrations.py index 26e5f115c5c3..c66f3187e39d 100644 --- a/nova/tests/functional/db/api/test_migrations.py +++ b/nova/tests/functional/db/api/test_migrations.py @@ -35,6 +35,7 @@ import mock from oslo_db.sqlalchemy import test_base from oslo_db.sqlalchemy import test_migrations from oslo_db.sqlalchemy import utils as db_utils +from oslo_serialization import jsonutils import sqlalchemy from sqlalchemy.engine import reflection @@ -43,6 +44,7 @@ from nova.db.sqlalchemy.api_migrations import migrate_repo from nova.db.sqlalchemy import api_models from nova.db.sqlalchemy import migration as sa_migration from nova import test +from nova.test import uuids from nova.tests import fixtures as nova_fixtures @@ -654,6 +656,34 @@ class NovaAPIMigrationsWalk(test_migrations.WalkVersionsMixin): self.assertIndexExists(engine, 'resource_providers', 'resource_providers_parent_provider_id_idx') + def _pre_upgrade_052(self, engine): + request_specs = db_utils.get_table(engine, 'request_specs') + # The spec value is a serialized json blob. + spec = jsonutils.dumps( + {"instance_group": {"id": 42, + "members": ["uuid1", + "uuid2", + "uuid3"]}}) + fake_request_spec = { + 'id': 42, 'spec': spec, 'instance_uuid': uuids.instance} + request_specs.insert().execute(fake_request_spec) + + def _check_052(self, engine, data): + request_specs = db_utils.get_table(engine, 'request_specs') + if engine.name == 'mysql': + self.assertIsInstance(request_specs.c.spec.type, + sqlalchemy.dialects.mysql.MEDIUMTEXT) + + expected_spec = {"instance_group": {"id": 42, + "members": ["uuid1", + "uuid2", + "uuid3"]}} + from_db_request_spec = request_specs.select( + request_specs.c.id == 42).execute().first() + self.assertEqual(uuids.instance, from_db_request_spec['instance_uuid']) + db_spec = jsonutils.loads(from_db_request_spec['spec']) + self.assertDictEqual(expected_spec, db_spec) + class TestNovaAPIMigrationsWalkSQLite(NovaAPIMigrationsWalk, test_base.DbTestCase,