diff --git a/cinderlib/persistence/dbms.py b/cinderlib/persistence/dbms.py index 4eaef5c..4ace074 100644 --- a/cinderlib/persistence/dbms.py +++ b/cinderlib/persistence/dbms.py @@ -21,6 +21,7 @@ from cinder.db.sqlalchemy import api as sqla_api from cinder.db.sqlalchemy import models from cinder import exception as cinder_exception from cinder import objects as cinder_objs +import migrate from oslo_config import cfg from oslo_db import exception from oslo_log import log @@ -70,7 +71,15 @@ class DBPersistence(persistence_base.PersistenceDriverBase): self.original_get_by_id = self.db_instance.get_by_id self.db_instance.get_by_id = self.get_by_id - migration.db_sync() + try: + migration.db_sync() + except exception.DBMigrationError as exc: + # We can be running 2 Cinder versions at the same time on the same + # DB while we upgrade, so we must ignore the fact that the DB is + # now on a newer version. + if not isinstance(getattr(exc, 'inner_exception', None), + migrate.exceptions.VersionNotFoundError): + raise self._create_key_value_table() # NOTE : At this point, the persistence isn't ready so we need to use diff --git a/cinderlib/tests/unit/persistence/test_dbms.py b/cinderlib/tests/unit/persistence/test_dbms.py index a42314c..1b40ca3 100644 --- a/cinderlib/tests/unit/persistence/test_dbms.py +++ b/cinderlib/tests/unit/persistence/test_dbms.py @@ -14,6 +14,7 @@ # under the License. import tempfile +from unittest import mock from cinder.db.sqlalchemy import api as sqla_api from cinder import objects as cinder_ovos @@ -136,5 +137,31 @@ class TestDBPersistence(base.BasePersistenceTest): self.assertEqual([], res) +class TestDBPersistenceNewerSchema(base.helper.TestHelper): + """Test DBMS plugin can start when the DB has a newer schema.""" + CONNECTION = 'sqlite:///' + tempfile.NamedTemporaryFile().name + PERSISTENCE_CFG = {'storage': 'db', + 'connection': CONNECTION} + + @classmethod + def setUpClass(cls): + pass + + def _raise_exc(self): + inner_exc = dbms.migrate.exceptions.VersionNotFoundError() + exc = dbms.exception.DBMigrationError(inner_exc) + self.original_db_sync() + raise(exc) + + def test_newer_db_schema(self): + self.original_db_sync = dbms.migration.db_sync + with mock.patch.object(dbms.migration, 'db_sync', + side_effect=self._raise_exc) as db_sync_mock: + super(TestDBPersistenceNewerSchema, self).setUpClass() + db_sync_mock.assert_called_once() + self.assertIsInstance(cinderlib.Backend.persistence, + dbms.DBPersistence) + + class TestMemoryDBPersistence(TestDBPersistence): PERSISTENCE_CFG = {'storage': 'memory_db'} diff --git a/releasenotes/notes/mysql-db-sync-8a9e50a12bbe724d.yaml b/releasenotes/notes/mysql-db-sync-8a9e50a12bbe724d.yaml new file mode 100644 index 0000000..b75e8d7 --- /dev/null +++ b/releasenotes/notes/mysql-db-sync-8a9e50a12bbe724d.yaml @@ -0,0 +1,6 @@ +--- +fixes: + - | + Bug #1868145: Support rolling upgrades with the DBMS persistence plugin. + Can run an N release version even if we have already run once an N+1 + release.