Revert status to previous state on extend failure

When Cinder fails to schedule extend volume action, the
status will be set to 'available' no matter what the
previous status is.

Change-Id: I830c11cda252fe25e1c069a425bdebe8c98f7a8d
Closes-Bug: 1718374
This commit is contained in:
TommyLike 2017-09-20 16:29:10 +08:00
parent 6c236bca3d
commit ce3830a01a
4 changed files with 19 additions and 7 deletions

View File

@ -339,7 +339,8 @@ class SchedulerManager(manager.CleanableManager, manager.Manager):
request_spec=None, filter_properties=None):
def _extend_volume_set_error(self, context, ex, request_spec):
volume_state = {'volume_state': {'status': 'available'}}
volume_state = {'volume_state': {'status': volume.previous_status,
'previous_status': None}}
self._set_volume_state_and_notify('extend_volume', volume_state,
context, ex, request_spec)

View File

@ -19,7 +19,7 @@ Tests For Scheduler
import collections
from datetime import datetime
import ddt
import mock
from oslo_config import cfg
@ -38,6 +38,7 @@ from cinder.tests.unit import utils as tests_utils
CONF = cfg.CONF
@ddt.ddt
class SchedulerManagerTestCase(test.TestCase):
"""Test case for scheduler manager."""
@ -117,14 +118,18 @@ class SchedulerManagerTestCase(test.TestCase):
mock_extend.assert_called_once_with(
self.context, volume, 2, 'fake_reservation')
@ddt.data('available', 'in-use')
@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})
def test_extend_volume_no_valid_host(self, status, mock_rollback,
mock_extend, mock_consume,
mock_backend_passes):
volume = fake_volume.fake_volume_obj(self.context,
**{'size': 1,
'previous_status': status})
no_valid_backend = exception.NoValidBackend(reason='')
mock_backend_passes.side_effect = [no_valid_backend]
@ -133,7 +138,8 @@ class SchedulerManagerTestCase(test.TestCase):
self.manager.extend_volume(self.context, volume, 2,
'fake_reservation')
mock_notify.assert_called_once_with(
'extend_volume', {'volume_state': {'status': 'available'}},
'extend_volume', {'volume_state': {'status': status,
'previous_status': None}},
self.context, no_valid_backend, None)
mock_rollback.assert_called_once_with(
self.context, 'fake_reservation', project_id=volume.project_id)

View File

@ -2051,10 +2051,12 @@ class VolumeTestCase(base.BaseVolumeTestCase):
volume, 3, attached=True)
db.volume_update(self.context, volume.id, {'status': 'in-use'})
volume.refresh()
reserve.return_value = ["RESERVATION"]
volume_api._extend(self.context, volume, 3, attached=True)
volume.refresh()
self.assertEqual('extending', volume.status)
self.assertEqual('in-use', volume.previous_status)
reserve.assert_called_once_with(self.context, gigabytes=1,
project_id=volume.project_id)
limit_check.side_effect = None
@ -2091,6 +2093,7 @@ class VolumeTestCase(base.BaseVolumeTestCase):
3)
db.volume_update(self.context, volume.id, {'status': 'available'})
volume.refresh()
# Extend fails when new_size < orig_size
self.assertRaises(exception.InvalidInput,
volume_api._extend,
@ -2110,6 +2113,7 @@ class VolumeTestCase(base.BaseVolumeTestCase):
volume_api._extend(self.context, volume, 3)
volume.refresh()
self.assertEqual('extending', volume.status)
self.assertEqual('available', volume.previous_status)
reserve.assert_called_once_with(self.context, gigabytes=1,
project_id=volume.project_id)

View File

@ -1301,7 +1301,8 @@ class API(base.Base):
return response
def _extend(self, context, volume, new_size, attached=False):
value = {'status': 'extending'}
value = {'status': 'extending',
'previous_status': volume.status}
if attached:
expected = {'status': 'in-use'}
else: