Skip to content

Commit e463447

Browse files
Zuulopenstack-gerrit
authored andcommitted
Merge "Only call _fill_provider_mapping if claim succeeds"
2 parents e804e18 + a9324ad commit e463447

File tree

2 files changed

+84
-1
lines changed

2 files changed

+84
-1
lines changed

nova/conductor/manager.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -686,7 +686,7 @@ def build_instances(self, context, instances, image, filter_properties,
686686
elevated, self.report_client, spec_obj,
687687
instance.uuid, alloc_req,
688688
host.allocation_request_version)
689-
if request_spec:
689+
if request_spec and host_available:
690690
# NOTE(gibi): redo the request group - resource
691691
# provider mapping as the above claim call
692692
# moves the allocation of the instance to

nova/tests/unit/conductor/test_conductor.py

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1027,6 +1027,89 @@ def do_test(mock_destroy_build_req, mock_pop_inst_map,
10271027

10281028
do_test()
10291029

1030+
@mock.patch.object(objects.Instance, 'save', new=mock.MagicMock())
1031+
@mock.patch.object(query.SchedulerQueryClient, 'select_destinations')
1032+
@mock.patch.object(conductor_manager.ComputeTaskManager,
1033+
'_set_vm_state_and_notify', new=mock.MagicMock())
1034+
def test_build_instances_reschedule_not_recalc_mapping_if_claim_fails(
1035+
self, mock_select_dests):
1036+
1037+
rg1 = objects.RequestGroup(resources={"CUSTOM_FOO": 1})
1038+
request_spec = objects.RequestSpec(requested_resources=[rg1])
1039+
1040+
mock_select_dests.return_value = [[fake_selection1]]
1041+
instance = fake_instance.fake_instance_obj(self.context)
1042+
image = {'fake-data': 'should_pass_silently'}
1043+
1044+
# build_instances() is a cast, we need to wait for it to complete
1045+
self.useFixture(cast_as_call.CastAsCall(self))
1046+
1047+
@mock.patch('nova.conductor.manager.ComputeTaskManager.'
1048+
'_fill_provider_mapping')
1049+
@mock.patch('nova.scheduler.utils.claim_resources',
1050+
# simulate that the first claim fails during re-schedule
1051+
side_effect=[False, True])
1052+
@mock.patch('nova.objects.request_spec.RequestSpec.from_primitives',
1053+
return_value=request_spec)
1054+
@mock.patch.object(self.conductor_manager.compute_rpcapi,
1055+
'build_and_run_instance')
1056+
@mock.patch.object(self.conductor_manager,
1057+
'_populate_instance_mapping')
1058+
@mock.patch.object(self.conductor_manager, '_destroy_build_request')
1059+
def do_test(mock_destroy_build_req, mock_pop_inst_map,
1060+
mock_build_and_run, mock_request_spec_from_primitives,
1061+
mock_claim, mock_rp_mapping):
1062+
self.conductor.build_instances(
1063+
context=self.context,
1064+
instances=[instance],
1065+
image=image,
1066+
filter_properties={'retry': {'num_attempts': 1, 'hosts': []}},
1067+
admin_password='admin_password',
1068+
injected_files='injected_files',
1069+
requested_networks=None,
1070+
security_groups='security_groups',
1071+
block_device_mapping='block_device_mapping',
1072+
legacy_bdm=False,
1073+
host_lists=copy.deepcopy(fake_host_lists_alt),
1074+
request_spec=request_spec)
1075+
1076+
expected_build_run_host_list = copy.copy(fake_host_lists_alt[0])
1077+
if expected_build_run_host_list:
1078+
# first is consumed but the claim fails so the conductor takes
1079+
# the next host
1080+
expected_build_run_host_list.pop(0)
1081+
# second is consumed and claim succeeds
1082+
expected_build_run_host_list.pop(0)
1083+
mock_build_and_run.assert_called_with(
1084+
self.context,
1085+
instance=mock.ANY,
1086+
host='host2',
1087+
image=image,
1088+
request_spec=request_spec,
1089+
filter_properties={'retry': {'num_attempts': 2,
1090+
'hosts': [['host2', 'node2']]},
1091+
'limits': {}},
1092+
admin_password='admin_password',
1093+
injected_files='injected_files',
1094+
requested_networks=None,
1095+
security_groups='security_groups',
1096+
block_device_mapping=test.MatchType(
1097+
objects.BlockDeviceMappingList),
1098+
node='node2',
1099+
limits=None,
1100+
host_list=expected_build_run_host_list)
1101+
1102+
# called only once when the claim succeeded
1103+
mock_rp_mapping.assert_called_once_with(
1104+
self.context, instance.uuid, mock.ANY,
1105+
test.MatchType(objects.Selection))
1106+
actual_request_spec = mock_rp_mapping.mock_calls[0][1][2]
1107+
self.assertEqual(
1108+
rg1.resources,
1109+
actual_request_spec.requested_resources[0].resources)
1110+
1111+
do_test()
1112+
10301113
@mock.patch.object(cinder.API, 'attachment_get')
10311114
@mock.patch.object(cinder.API, 'attachment_create')
10321115
@mock.patch.object(block_device_obj.BlockDeviceMapping, 'save')

0 commit comments

Comments
 (0)