Improve migration_get_progress error handling

Share manager may raise InvalidShare because the migration phase
has already been completed. In such cases total_progress 100 can
be reported instead of raising ShareMigrationError.

Change-Id: I6e1b1abf6a2fd8c1268e446b7ee8e364bdc496bc
Closes-Bug: #1889549
This commit is contained in:
Maurice Escher 2020-07-31 14:04:04 +02:00
parent 5f433b59ba
commit fec7643a85
No known key found for this signature in database
GPG Key ID: CC56DEC23EE46750
3 changed files with 46 additions and 0 deletions

View File

@ -1565,6 +1565,10 @@ class API(base.Base):
try:
result = self.share_rpcapi.migration_get_progress(
context, share_instance_ref, migrating_instance_id)
except exception.InvalidShare:
# reload to get the latest task_state
share = self.db.share_get(context, share['id'])
result = self._migration_get_progress_state(share)
except Exception:
msg = _("Failed to obtain migration progress of share "
"%s.") % share['id']

View File

@ -5513,6 +5513,41 @@ class ShareAPITestCase(test.TestCase):
mock_get_destination.assert_called_once_with(
self.context, 'fake_src_server_id', status=constants.STATUS_ACTIVE)
def test_migration_get_progress_race(self):
instance1 = db_utils.create_share_instance(
share_id='fake_id',
status=constants.STATUS_MIGRATING,
host='some_host')
instance2 = db_utils.create_share_instance(
share_id='fake_id',
status=constants.STATUS_MIGRATING_TO)
share = db_utils.create_share(
id='fake_id',
task_state=constants.TASK_STATE_MIGRATION_DRIVER_IN_PROGRESS,
instances=[instance1, instance2])
share_ref = fakes.fake_share(
id='fake_id',
task_state=constants.TASK_STATE_MIGRATION_DRIVER_PHASE1_DONE)
service = 'fake_service'
expected = {'total_progress': 100}
self.mock_object(utils, 'service_is_up', mock.Mock(return_value=True))
self.mock_object(db_api, 'service_get_by_args',
mock.Mock(return_value=service))
self.mock_object(db_api, 'share_instance_get',
mock.Mock(return_value=instance1))
self.mock_object(db_api, 'share_get',
mock.Mock(return_value=share_ref))
self.mock_object(self.api.share_rpcapi, 'migration_get_progress',
mock.Mock(side_effect=exception.InvalidShare('fake')))
result = self.api.migration_get_progress(self.context, share)
self.assertEqual(expected, result)
self.api.share_rpcapi.migration_get_progress.assert_called_once_with(
self.context, instance1, instance2['id'])
class OtherTenantsShareActionsTestCase(test.TestCase):
def setUp(self):

View File

@ -0,0 +1,7 @@
---
fixes:
- |
In the share migration_get_progress API a race condition was fixed. If the
share manager reports ``InvalidShare`` the share's task state is evaluated
again to return progress 0 or 100 based on known task states instead of
raising ``ShareMigrationError``.