diff --git a/nova/db/sqlalchemy/api_migrations/migrate_repo/versions/031_request_specs_spec_mediumtext.py b/nova/db/sqlalchemy/api_migrations/migrate_repo/versions/031_request_specs_spec_mediumtext.py new file mode 100644 index 000000000000..e0eef79a022c --- /dev/null +++ b/nova/db/sqlalchemy/api_migrations/migrate_repo/versions/031_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 e5c5720dc3b0..586b8b3feab5 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 b66e2623dcac..d0e8c3c4ec8e 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 @@ -578,6 +580,34 @@ class NovaAPIMigrationsWalk(test_migrations.WalkVersionsMixin): for column in ['created_at', 'updated_at', 'id', 'uuid']: self.assertColumnExists(engine, 'placement_aggregates', column) + def _pre_upgrade_031(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_031(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, diff --git a/releasenotes/notes/bug-1738094-request_specs.spec-migration-22d3421ea1536a37.yaml b/releasenotes/notes/bug-1738094-request_specs.spec-migration-22d3421ea1536a37.yaml new file mode 100644 index 000000000000..c333cc93e748 --- /dev/null +++ b/releasenotes/notes/bug-1738094-request_specs.spec-migration-22d3421ea1536a37.yaml @@ -0,0 +1,11 @@ +--- +upgrade: + - | + This release contains a schema migration for the ``nova_api`` database + in order to address bug 1738094: + + https://bugs.launchpad.net/nova/+bug/1738094 + + The migration is optional and can be postponed if you have not been + affected by the bug. The bug manifests itself through "Data too long for + column 'spec'" database errors.