22
22
import operator
23
23
import sys
24
24
import time
25
- import traceback
26
25
27
26
import ddt
28
27
@@ -12789,62 +12788,6 @@ def fake_get_flavor_by_flavor_id(flavor_id, ctxt=None,
12789
12788
self.compute_api.resize, self.context, instance, '4')
12790
12789
12791
12790
12792
- class ComputeReschedulingTestCase(BaseTestCase):
12793
- """Tests re-scheduling logic for new build requests."""
12794
-
12795
- def setUp(self):
12796
- super(ComputeReschedulingTestCase, self).setUp()
12797
-
12798
- self.expected_task_state = task_states.SCHEDULING
12799
-
12800
- def fake_update(*args, **kwargs):
12801
- self.updated_task_state = kwargs.get('task_state')
12802
- self.stub_out('nova.compute.manager.ComputeManager._instance_update',
12803
- fake_update)
12804
-
12805
- def _reschedule(self, request_spec=None, filter_properties=None,
12806
- exc_info=None):
12807
- if not filter_properties:
12808
- filter_properties = {}
12809
- fake_taskapi = FakeComputeTaskAPI()
12810
- with mock.patch.object(self.compute, 'compute_task_api',
12811
- fake_taskapi):
12812
- instance = self._create_fake_instance_obj()
12813
-
12814
- scheduler_method = self.compute.compute_task_api.resize_instance
12815
- method_args = (instance, None,
12816
- dict(filter_properties=filter_properties),
12817
- {}, None)
12818
- return self.compute._reschedule(self.context, request_spec,
12819
- filter_properties, instance, scheduler_method,
12820
- method_args, self.expected_task_state, exc_info=exc_info)
12821
-
12822
- def test_reschedule_no_filter_properties(self):
12823
- # no filter_properties will disable re-scheduling.
12824
- self.assertFalse(self._reschedule())
12825
-
12826
- def test_reschedule_no_retry_info(self):
12827
- # no retry info will also disable re-scheduling.
12828
- filter_properties = {}
12829
- self.assertFalse(self._reschedule(filter_properties=filter_properties))
12830
-
12831
- def test_reschedule_success(self):
12832
- retry = dict(num_attempts=1)
12833
- filter_properties = dict(retry=retry)
12834
- request_spec = {'num_instances': 1}
12835
- try:
12836
- raise test.TestingException("just need an exception")
12837
- except test.TestingException:
12838
- exc_info = sys.exc_info()
12839
- exc_str = traceback.format_exception_only(exc_info[0],
12840
- exc_info[1])
12841
-
12842
- self.assertTrue(self._reschedule(filter_properties=filter_properties,
12843
- request_spec=request_spec, exc_info=exc_info))
12844
- self.assertEqual(self.updated_task_state, self.expected_task_state)
12845
- self.assertEqual(exc_str, filter_properties['retry']['exc'])
12846
-
12847
-
12848
12791
class InnerTestingException(Exception):
12849
12792
pass
12850
12793
@@ -12859,6 +12802,7 @@ def setUp(self):
12859
12802
self.instance_uuid = self.instance['uuid']
12860
12803
self.instance_type = objects.Flavor.get_by_name(
12861
12804
context.get_admin_context(), 'm1.tiny')
12805
+ self.request_spec = objects.RequestSpec()
12862
12806
12863
12807
@mock.patch('nova.compute.manager.ComputeManager._prep_resize',
12864
12808
side_effect=test.TestingException)
@@ -12873,93 +12817,113 @@ def test_reschedule_resize_or_reraise_called(self, mock_res, mock_prep):
12873
12817
self.compute.prep_resize(self.context, image=None,
12874
12818
instance=inst_obj,
12875
12819
instance_type=self.instance_type,
12876
- request_spec=mock.sentinel.reqspec ,
12820
+ request_spec=self.request_spec ,
12877
12821
filter_properties={}, migration=mock.Mock(),
12878
12822
node=None,
12879
12823
clean_shutdown=True, host_list=None)
12880
12824
12881
12825
mock_res.assert_called_once_with(mock.ANY, inst_obj, mock.ANY,
12882
12826
self.instance_type,
12883
- mock.sentinel.reqspec , {}, None)
12827
+ self.request_spec , {}, None)
12884
12828
12885
- @mock.patch.object(compute_manager.ComputeManager, "_reschedule")
12886
- @mock.patch('nova.compute.utils.notify_about_instance_action')
12887
- def test_reschedule_fails_with_exception(self, mock_notify, mock_res):
12888
- """Original exception should be raised if the _reschedule method
12889
- raises another exception
12829
+ def test_reschedule_resize_or_reraise_no_filter_properties(self):
12830
+ """Test behavior when ``filter_properties`` is None.
12831
+
12832
+ This should disable rescheduling and the original exception should be
12833
+ raised.
12890
12834
"""
12891
- instance = self._create_fake_instance_obj()
12892
- scheduler_hint = dict(filter_properties={})
12893
- method_args = (instance, None, scheduler_hint, self.instance_type)
12894
- mock_res.side_effect = InnerTestingException("Inner")
12835
+ filter_properties = None
12895
12836
12896
12837
try:
12897
12838
raise test.TestingException("Original")
12898
12839
except Exception:
12899
12840
exc_info = sys.exc_info()
12900
- reqspec = objects.RequestSpec()
12841
+ # because we're not retrying, we should re-raise the exception
12901
12842
self.assertRaises(test.TestingException,
12902
- self.compute._reschedule_resize_or_reraise, self.context,
12903
- instance, exc_info, self.instance_type, reqspec,
12904
- {}, None)
12905
-
12906
- mock_res.assert_called_once_with(
12907
- self.context, reqspec, {}, instance,
12908
- self.compute.compute_task_api.resize_instance, method_args,
12909
- task_states.RESIZE_PREP, exc_info, host_list=None)
12910
- mock_notify.assert_called_once_with(
12911
- self.context, instance, 'fake-mini', action='resize',
12912
- phase='error', exception=mock_res.side_effect, tb=mock.ANY)
12843
+ self.compute._reschedule_resize_or_reraise, self.context,
12844
+ self.instance, exc_info, self.instance_type,
12845
+ self.request_spec, filter_properties, None)
12846
+
12847
+ def test_reschedule_resize_or_reraise_no_retry_info(self):
12848
+ """Test behavior when ``filter_properties`` doesn't contain 'retry'.
12913
12849
12914
- @mock.patch.object(compute_manager.ComputeManager, "_reschedule")
12915
- def test_reschedule_false(self, mock_res):
12916
- """Original exception should be raised if the resize is not
12917
- rescheduled.
12850
+ This should disable rescheduling and the original exception should be
12851
+ raised.
12918
12852
"""
12919
- instance = self._create_fake_instance_obj()
12920
- scheduler_hint = dict(filter_properties={})
12921
- method_args = (instance, None, scheduler_hint, self.instance_type)
12922
- mock_res.return_value = False
12853
+ filter_properties = {}
12923
12854
12924
12855
try:
12925
12856
raise test.TestingException("Original")
12926
12857
except Exception:
12927
12858
exc_info = sys.exc_info()
12928
- reqspec = objects.RequestSpec()
12859
+ # because we're not retrying, we should re-raise the exception
12929
12860
self.assertRaises(test.TestingException,
12930
- self.compute._reschedule_resize_or_reraise, self.context,
12931
- instance, exc_info, self.instance_type, reqspec,
12932
- {}, None)
12861
+ self.compute._reschedule_resize_or_reraise, self.context,
12862
+ self.instance, exc_info, self.instance_type,
12863
+ self.request_spec, filter_properties, None)
12864
+
12865
+ @mock.patch.object(compute_manager.ComputeManager, '_instance_update')
12866
+ @mock.patch('nova.conductor.api.ComputeTaskAPI.resize_instance',
12867
+ side_effect=InnerTestingException('inner'))
12868
+ @mock.patch('nova.compute.utils.notify_about_instance_action')
12869
+ @mock.patch.object(compute_manager.ComputeManager, "_log_original_error")
12870
+ def test_reschedule_fails_with_exception(self, mock_log, mock_notify,
12871
+ mock_resize, mock_update):
12872
+ """Original exception should be raised if the conductor call
12873
+ raises another exception.
12874
+ """
12875
+ filter_properties = {'retry': {'num_attempts': 0}}
12933
12876
12934
- mock_res.assert_called_once_with(
12935
- self.context, reqspec, {}, instance,
12936
- self.compute.compute_task_api.resize_instance, method_args,
12937
- task_states.RESIZE_PREP, exc_info, host_list=None)
12877
+ try:
12878
+ raise test.TestingException('Original')
12879
+ except Exception:
12880
+ exc_info = sys.exc_info()
12881
+ self.assertRaises(test.TestingException,
12882
+ self.compute._reschedule_resize_or_reraise, self.context,
12883
+ self.instance, exc_info, self.instance_type,
12884
+ self.request_spec, filter_properties, None)
12885
+
12886
+ mock_update.assert_called_once_with(
12887
+ self.context, mock.ANY, task_state=task_states.RESIZE_PREP)
12888
+ mock_resize.assert_called_once_with(
12889
+ self.context, mock.ANY, None,
12890
+ {'filter_properties': filter_properties}, self.instance_type,
12891
+ request_spec=self.request_spec, host_list=None)
12892
+ mock_notify.assert_called_once_with(
12893
+ self.context, self.instance, 'fake-mini', action='resize',
12894
+ phase='error', exception=mock_resize.side_effect, tb=mock.ANY)
12895
+ # If not rescheduled, the original resize exception should not be
12896
+ # logged.
12897
+ mock_log.assert_not_called()
12938
12898
12939
- @mock.patch.object(compute_manager.ComputeManager, "_reschedule")
12899
+ @mock.patch.object(compute_manager.ComputeManager, '_instance_update')
12900
+ @mock.patch('nova.conductor.api.ComputeTaskAPI.resize_instance')
12901
+ @mock.patch('nova.compute.utils.notify_about_instance_action')
12940
12902
@mock.patch.object(compute_manager.ComputeManager, "_log_original_error")
12941
- def test_reschedule_true(self, mock_log, mock_res):
12942
- # If rescheduled, the original resize exception should be logged.
12943
- instance = self._create_fake_instance_obj()
12944
- scheduler_hint = dict(filter_properties={})
12945
- method_args = (instance, None, scheduler_hint, self.instance_type)
12903
+ def test_reschedule_passes(self, mock_log, mock_notify, mock_resize,
12904
+ mock_update):
12905
+ filter_properties = {'retry': {'num_attempts': 0}}
12946
12906
12947
12907
try:
12948
12908
raise test.TestingException("Original")
12949
12909
except Exception:
12950
12910
exc_info = sys.exc_info()
12951
- mock_res.return_value = True
12952
12911
12953
- reqspec = objects.RequestSpec()
12954
12912
self.compute._reschedule_resize_or_reraise(
12955
- self.context, instance, exc_info,
12956
- self.instance_type, reqspec, {}, None)
12957
-
12958
- mock_res.assert_called_once_with(self.context, reqspec, {},
12959
- instance, self.compute.compute_task_api.resize_instance,
12960
- method_args, task_states.RESIZE_PREP, exc_info,
12961
- host_list=None)
12962
- mock_log.assert_called_once_with(exc_info, instance.uuid)
12913
+ self.context, self.instance, exc_info, self.instance_type,
12914
+ self.request_spec, filter_properties, None)
12915
+
12916
+ mock_update.assert_called_once_with(
12917
+ self.context, mock.ANY, task_state=task_states.RESIZE_PREP)
12918
+ mock_resize.assert_called_once_with(
12919
+ self.context, mock.ANY, None,
12920
+ {'filter_properties': filter_properties}, self.instance_type,
12921
+ request_spec=self.request_spec, host_list=None)
12922
+ mock_notify.assert_called_once_with(
12923
+ self.context, self.instance, 'fake-mini', action='resize',
12924
+ phase='error', exception=exc_info[1], tb=mock.ANY)
12925
+ # If rescheduled, the original resize exception should be logged.
12926
+ mock_log.assert_called_once_with(exc_info, self.instance.uuid)
12963
12927
12964
12928
12965
12929
class ComputeInactiveImageTestCase(BaseTestCase):
0 commit comments