diff --git a/cinder/db/api.py b/cinder/db/api.py index 9c5d7e7e56e..6e1fc939798 100644 --- a/cinder/db/api.py +++ b/cinder/db/api.py @@ -1892,17 +1892,6 @@ def cleanup_expired_messages(context): ################### -def workers_init(): - """Check if DB supports subsecond resolution and set global flag. - - MySQL 5.5 doesn't support subsecond resolution in datetime fields, so we - have to take it into account when working with the worker's table. - - Once we drop support for MySQL 5.5 we can remove this method. - """ - return IMPL.workers_init() - - def worker_create(context, **values): """Create a worker entry from optional arguments.""" return IMPL.worker_create(context, **values) diff --git a/cinder/db/sqlalchemy/api.py b/cinder/db/sqlalchemy/api.py index 494454bb9dd..137837e0b4c 100644 --- a/cinder/db/sqlalchemy/api.py +++ b/cinder/db/sqlalchemy/api.py @@ -7272,7 +7272,9 @@ def _worker_query(context, session=None, until=None, db_filters=None, query = model_query(context, models.Worker, session=session) - # TODO(geguileo): Once we remove support for MySQL 5.5 we can remove this + # TODO: Once we stop creating the SENTINEL entry in the database (which + # was only needed to support MySQL 5.5), we can drop this. Probably in the + # A release or later if ignore_sentinel: # We don't want to retrieve the workers sentinel query = query.filter(models.Worker.resource_type != 'SENTINEL') @@ -7292,35 +7294,10 @@ def _worker_query(context, session=None, until=None, db_filters=None, return query -DB_SUPPORTS_SUBSECOND_RESOLUTION = True - - -def workers_init(): - """Check if DB supports subsecond resolution and set global flag. - - MySQL 5.5 doesn't support subsecond resolution in datetime fields, so we - have to take it into account when working with the worker's table. - - To do this we'll have 1 row in the DB, created by the migration script, - where we have tried to set the microseconds and we'll check it. - - Once we drop support for MySQL 5.5 we can remove this method. - """ - global DB_SUPPORTS_SUBSECOND_RESOLUTION - session = get_session() - query = session.query(models.Worker).filter_by(resource_type='SENTINEL') - worker = query.first() - DB_SUPPORTS_SUBSECOND_RESOLUTION = bool(worker.updated_at.microsecond) - - def _worker_set_updated_at_field(values): - # TODO(geguileo): Once we drop support for MySQL 5.5 we can simplify this - # method. updated_at = values.get('updated_at', timeutils.utcnow()) if isinstance(updated_at, str): return - if not DB_SUPPORTS_SUBSECOND_RESOLUTION: - updated_at = updated_at.replace(microsecond=0) values['updated_at'] = updated_at diff --git a/cinder/manager.py b/cinder/manager.py index 373fe0923a9..7b9399c2e83 100644 --- a/cinder/manager.py +++ b/cinder/manager.py @@ -318,8 +318,5 @@ class CleanableManager(object): def init_host(self, service_id, added_to_cluster=None, **kwargs): ctxt = context.get_admin_context() self.service_id = service_id - # TODO(geguileo): Once we don't support MySQL 5.5 anymore we can remove - # call to workers_init. - db.workers_init() cleanup_request = objects.CleanupRequest(service_id=service_id) self.do_cleanup(ctxt, cleanup_request) diff --git a/cinder/tests/unit/test_cleanable_manager.py b/cinder/tests/unit/test_cleanable_manager.py index 043b2c98929..96f8728bf72 100644 --- a/cinder/tests/unit/test_cleanable_manager.py +++ b/cinder/tests/unit/test_cleanable_manager.py @@ -47,9 +47,8 @@ class TestCleanableManager(test.TestCase): is_admin=True) self.service = db.service_create(self.context, {}) - @mock.patch('cinder.db.workers_init', autospec=True) @mock.patch('cinder.manager.CleanableManager.do_cleanup', autospec=True) - def test_init_host_with_service(self, mock_cleanup, mock_workers_init): + def test_init_host_with_service(self, mock_cleanup): mngr = FakeManager() self.assertFalse(hasattr(mngr, 'service_id')) mngr.init_host(service_id=self.service.id) @@ -59,7 +58,6 @@ class TestCleanableManager(test.TestCase): clean_req = mock_cleanup.call_args[0][2] self.assertIsInstance(clean_req, objects.CleanupRequest) self.assertEqual(self.service.id, clean_req.service_id) - mock_workers_init.assert_called_once_with() def test_do_cleanup(self): """Basic successful cleanup.""" diff --git a/cinder/tests/unit/test_db_worker_api.py b/cinder/tests/unit/test_db_worker_api.py index 62220baa0fc..bf6d8f1dbf6 100644 --- a/cinder/tests/unit/test_db_worker_api.py +++ b/cinder/tests/unit/test_db_worker_api.py @@ -15,9 +15,7 @@ """Unit tests for cinder.db.api.Worker""" -from datetime import datetime import time -from unittest import mock import uuid from oslo_db import exception as db_exception @@ -41,41 +39,12 @@ class DBAPIWorkerTestCase(test.TestCase, test.ModelsObjectComparatorMixin): super(DBAPIWorkerTestCase, self).setUp() self.ctxt = context.get_admin_context() - def tearDown(self): - db.sqlalchemy.api.DB_SUPPORTS_SUBSECOND_RESOLUTION = True - super(DBAPIWorkerTestCase, self).tearDown() - - def test_workers_init(self): - # SQLite supports subsecond resolution so result is True - db.sqlalchemy.api.DB_SUPPORTS_SUBSECOND_RESOLUTION = None - db.workers_init() - self.assertTrue(db.sqlalchemy.api.DB_SUPPORTS_SUBSECOND_RESOLUTION) - - def test_workers_init_not_supported(self): - # Fake a Db that doesn't support sub-second resolution in datetimes - db.worker_update( - self.ctxt, None, - {'resource_type': 'SENTINEL', 'ignore_sentinel': False}, - updated_at=datetime.utcnow().replace(microsecond=0)) - db.workers_init() - self.assertFalse(db.sqlalchemy.api.DB_SUPPORTS_SUBSECOND_RESOLUTION) - def test_worker_create_and_get(self): """Test basic creation of a worker record.""" worker = db.worker_create(self.ctxt, **self.worker_fields) db_worker = db.worker_get(self.ctxt, id=worker.id) self._assertEqualObjects(worker, db_worker) - @mock.patch('oslo_utils.timeutils.utcnow', - return_value=datetime.utcnow().replace(microsecond=123)) - def test_worker_create_no_subsecond(self, mock_utcnow): - """Test basic creation of a worker record.""" - db.sqlalchemy.api.DB_SUPPORTS_SUBSECOND_RESOLUTION = False - worker = db.worker_create(self.ctxt, **self.worker_fields) - db_worker = db.worker_get(self.ctxt, id=worker.id) - self._assertEqualObjects(worker, db_worker) - self.assertEqual(0, db_worker.updated_at.microsecond) - def test_worker_create_unique_constrains(self): """Test when we use an already existing resource type and id.""" db.worker_create(self.ctxt, **self.worker_fields) @@ -163,23 +132,6 @@ class DBAPIWorkerTestCase(test.TestCase, test.ModelsObjectComparatorMixin): ['updated_at', 'race_preventer']) self.assertEqual(worker.race_preventer + 1, db_worker.race_preventer) - def test_worker_update_no_subsecond(self): - """Test basic worker update.""" - db.sqlalchemy.api.DB_SUPPORTS_SUBSECOND_RESOLUTION = False - worker = self._create_workers(1)[0] - worker = db.worker_get(self.ctxt, id=worker.id) - now = datetime.utcnow().replace(microsecond=123) - with mock.patch('oslo_utils.timeutils.utcnow', return_value=now): - res = db.worker_update(self.ctxt, worker.id, service_id=1) - self.assertEqual(1, res) - worker.service_id = 1 - - db_worker = db.worker_get(self.ctxt, id=worker.id) - self._assertEqualObjects(worker, db_worker, - ['updated_at', 'race_preventer']) - self.assertEqual(0, db_worker.updated_at.microsecond) - self.assertEqual(worker.race_preventer + 1, db_worker.race_preventer) - def test_worker_update_update_orm(self): """Test worker update updating the worker orm object.""" worker = self._create_workers(1)[0] diff --git a/releasenotes/notes/drop-mysql-5-5-support-fe3ececc3c9b9915.yaml b/releasenotes/notes/drop-mysql-5-5-support-fe3ececc3c9b9915.yaml new file mode 100644 index 00000000000..a6945f61675 --- /dev/null +++ b/releasenotes/notes/drop-mysql-5-5-support-fe3ececc3c9b9915.yaml @@ -0,0 +1,4 @@ +--- +upgrade: + - | + Support for MySQL 5.5 has been dropped.