diff --git a/cinder/scheduler/manager.py b/cinder/scheduler/manager.py index ab1c3d5e714..86611782204 100644 --- a/cinder/scheduler/manager.py +++ b/cinder/scheduler/manager.py @@ -348,9 +348,12 @@ class SchedulerManager(manager.CleanableManager, manager.Manager): filter_properties['new_size'] = new_size try: - self.driver.backend_passes_filters(context, - volume.service_topic_queue, - request_spec, filter_properties) + backend_state = self.driver.backend_passes_filters( + context, + volume.service_topic_queue, + request_spec, filter_properties) + backend_state.consume_from_volume( + {'size': new_size - volume.size}) volume_rpcapi.VolumeAPI().extend_volume(context, volume, new_size, reservations) except exception.NoValidBackend as ex: diff --git a/cinder/tests/unit/scheduler/test_scheduler.py b/cinder/tests/unit/scheduler/test_scheduler.py index 1e548f4e9ec..5c808b8ece8 100644 --- a/cinder/tests/unit/scheduler/test_scheduler.py +++ b/cinder/tests/unit/scheduler/test_scheduler.py @@ -32,6 +32,7 @@ from cinder.scheduler import manager from cinder import test from cinder.tests.unit import fake_constants as fake from cinder.tests.unit import fake_volume +from cinder.tests.unit.scheduler import fakes as fake_scheduler from cinder.tests.unit import utils as tests_utils CONF = cfg.CONF @@ -100,6 +101,45 @@ class SchedulerManagerTestCase(test.TestCase): mock_clean.assert_called_once_with(self.context) + @mock.patch('cinder.scheduler.driver.Scheduler.backend_passes_filters') + @mock.patch( + 'cinder.scheduler.host_manager.BackendState.consume_from_volume') + @mock.patch('cinder.volume.rpcapi.VolumeAPI.extend_volume') + def test_extend_volume(self, mock_extend, + mock_consume, mock_backend_passes): + volume = fake_volume.fake_volume_obj(self.context, **{'size': 1}) + fake_backend = fake_scheduler.FakeBackendState('host1', {}) + mock_backend_passes.return_value = fake_backend + + self.manager.extend_volume(self.context, volume, 2, 'fake_reservation') + + mock_consume.assert_called_once_with({'size': 1}) + mock_extend.assert_called_once_with( + self.context, volume, 2, 'fake_reservation') + + @mock.patch('cinder.scheduler.driver.Scheduler.backend_passes_filters') + @mock.patch( + 'cinder.scheduler.host_manager.BackendState.consume_from_volume') + @mock.patch('cinder.volume.rpcapi.VolumeAPI.extend_volume') + @mock.patch('cinder.quota.QUOTAS.rollback') + def test_extend_volume_no_valid_host(self, mock_rollback, mock_extend, + mock_consume, mock_backend_passes): + volume = fake_volume.fake_volume_obj(self.context, **{'size': 1}) + no_valid_backend = exception.NoValidBackend(reason='') + mock_backend_passes.side_effect = [no_valid_backend] + + with mock.patch.object(self.manager, + '_set_volume_state_and_notify') as mock_notify: + self.manager.extend_volume(self.context, volume, 2, + 'fake_reservation') + mock_notify.assert_called_once_with( + 'extend_volume', {'volume_state': {'status': 'available'}}, + self.context, no_valid_backend, None) + mock_rollback.assert_called_once_with( + self.context, 'fake_reservation', project_id=volume.project_id) + mock_consume.assert_not_called() + mock_extend.assert_not_called() + @mock.patch('cinder.quota.QuotaEngine.expire') def test_clean_expired_reservation(self, mock_clean): diff --git a/releasenotes/notes/bug-1706888-update-backend-when-extending-3e4a9831a0w29d68.yaml b/releasenotes/notes/bug-1706888-update-backend-when-extending-3e4a9831a0w29d68.yaml new file mode 100644 index 00000000000..650e88c9d36 --- /dev/null +++ b/releasenotes/notes/bug-1706888-update-backend-when-extending-3e4a9831a0w29d68.yaml @@ -0,0 +1,3 @@ +--- +fixes: + - Update backend state in scheduler when extending volume. \ No newline at end of file