diff options
author | Zuul <zuul@review.opendev.org> | 2019-11-04 11:52:51 +0000 |
---|---|---|
committer | Gerrit Code Review <review@openstack.org> | 2019-11-04 11:52:51 +0000 |
commit | c9f2e603d754660e5122992a1bcc28376ce699dc (patch) | |
tree | 01c476bbb0866770ad7163d9708a9f0298932e5c | |
parent | 9e8f1f2b8eb865433d2c70c8ff5f2626f13b8ad1 (diff) | |
parent | 32dbd2f585ef1902478170f3a1153b1f71e81db3 (diff) | |
download | nova-20.0.1.tar.gz |
Merge "Avoid error 500 on shelve task_state race" into stable/train20.0.1
-rw-r--r-- | nova/api/openstack/compute/shelve.py | 3 | ||||
-rw-r--r-- | nova/tests/unit/api/openstack/compute/test_shelve.py | 17 |
2 files changed, 19 insertions, 1 deletions
diff --git a/nova/api/openstack/compute/shelve.py b/nova/api/openstack/compute/shelve.py index b08a4ac7e9..ae8bea989c 100644 --- a/nova/api/openstack/compute/shelve.py +++ b/nova/api/openstack/compute/shelve.py @@ -48,7 +48,8 @@ class ShelveController(wsgi.Controller): 'project_id': instance.project_id}) try: self.compute_api.shelve(context, instance) - except exception.InstanceIsLocked as e: + except (exception.InstanceIsLocked, + exception.UnexpectedTaskStateError) as e: raise exc.HTTPConflict(explanation=e.format_message()) except exception.InstanceInvalidState as state_error: common.raise_http_conflict_for_instance_invalid_state(state_error, diff --git a/nova/tests/unit/api/openstack/compute/test_shelve.py b/nova/tests/unit/api/openstack/compute/test_shelve.py index 88488b9b33..8d41490d86 100644 --- a/nova/tests/unit/api/openstack/compute/test_shelve.py +++ b/nova/tests/unit/api/openstack/compute/test_shelve.py @@ -21,6 +21,7 @@ import webob from nova.api.openstack import api_version_request from nova.api.openstack.compute import shelve as shelve_v21 +from nova.compute import task_states from nova.compute import vm_states from nova import exception from nova import policy @@ -47,6 +48,22 @@ class ShelvePolicyTestV21(test.NoDBTestCase): self.req, uuidsentinel.fake, {}) @mock.patch('nova.api.openstack.common.get_instance') + @mock.patch('nova.objects.instance.Instance.save') + def test_shelve_task_state_race(self, mock_save, get_instance_mock): + instance = fake_instance.fake_instance_obj( + self.req.environ['nova.context'], + vm_state=vm_states.ACTIVE, task_state=None) + instance.launched_at = instance.created_at + get_instance_mock.return_value = instance + mock_save.side_effect = exception.UnexpectedTaskStateError( + instance_uuid=instance.uuid, expected=None, + actual=task_states.SHELVING) + ex = self.assertRaises(webob.exc.HTTPConflict, self.controller._shelve, + self.req, uuidsentinel.fake, body={'shelve': {}}) + self.assertIn('Conflict updating instance', six.text_type(ex)) + mock_save.assert_called_once_with(expected_task_state=[None]) + + @mock.patch('nova.api.openstack.common.get_instance') def test_unshelve_locked_server(self, get_instance_mock): get_instance_mock.return_value = ( fake_instance.fake_instance_obj(self.req.environ['nova.context'])) |