diff --git a/nova/scheduler/manager.py b/nova/scheduler/manager.py index 6472abaa3b45..b6979f88cc4d 100644 --- a/nova/scheduler/manager.py +++ b/nova/scheduler/manager.py @@ -130,9 +130,10 @@ class SchedulerManager(manager.Manager): raise exception.NoValidHost(reason=e.message) resources = utils.resources_from_request_spec(spec_obj) + is_rebuild = utils.request_is_rebuild(spec_obj) alloc_reqs_by_rp_uuid, provider_summaries, allocation_request_version \ = None, None, None - if self.driver.USES_ALLOCATION_CANDIDATES: + if self.driver.USES_ALLOCATION_CANDIDATES and not is_rebuild: res = self.placement_client.get_allocation_candidates(ctxt, resources) if res is None: diff --git a/nova/tests/functional/test_servers.py b/nova/tests/functional/test_servers.py index a1aa4303f80e..68e15c39a9bf 100644 --- a/nova/tests/functional/test_servers.py +++ b/nova/tests/functional/test_servers.py @@ -1257,6 +1257,15 @@ class ServerRebuildTestCase(integrated_helpers._IntegratedTestBase, return self.placement_api.get( '/allocations/%s' % server_uuid).body['allocations'] + def _set_provider_inventory(rp_uuid, resource_class, inventory): + # Get the resource provider generation for the inventory update. + rp = self.placement_api.get( + '/resource_providers/%s' % rp_uuid).body + inventory['resource_provider_generation'] = rp['generation'] + return self.placement_api.put( + '/resource_providers/%s/inventories/%s' % + (rp_uuid, resource_class), inventory).body + def assertFlavorMatchesAllocation(flavor, allocation): self.assertEqual(flavor['vcpus'], allocation['VCPU']) self.assertEqual(flavor['ram'], allocation['MEMORY_MB']) @@ -1285,6 +1294,9 @@ class ServerRebuildTestCase(integrated_helpers._IntegratedTestBase, flavor = self.api.api_get('/flavors/1').body['flavor'] + # make the compute node full and ensure rebuild still succeed + _set_provider_inventory(rp_uuid, "VCPU", {"total": 1}) + # There should be usage for the server on the compute node now. rp_usages = _get_provider_usages(rp_uuid) assertFlavorMatchesAllocation(flavor, rp_usages) diff --git a/nova/tests/unit/scheduler/test_scheduler.py b/nova/tests/unit/scheduler/test_scheduler.py index afd83061a633..e5998473d304 100644 --- a/nova/tests/unit/scheduler/test_scheduler.py +++ b/nova/tests/unit/scheduler/test_scheduler.py @@ -228,6 +228,22 @@ class SchedulerManagerTestCase(test.NoDBTestCase): place_res = ([], {}, None) self._test_select_destination(place_res) + @mock.patch('nova.scheduler.utils.resources_from_request_spec') + @mock.patch('nova.scheduler.client.report.SchedulerReportClient.' + 'get_allocation_candidates') + def test_select_destination_is_rebuild(self, mock_get_ac, mock_rfrs): + fake_spec = objects.RequestSpec( + scheduler_hints={'_nova_check_type': ['rebuild']}) + fake_spec.instance_uuid = uuids.instance + with mock.patch.object(self.manager.driver, 'select_destinations' + ) as select_destinations: + self.manager.select_destinations(self.context, spec_obj=fake_spec, + instance_uuids=[fake_spec.instance_uuid]) + select_destinations.assert_called_once_with( + self.context, fake_spec, + [fake_spec.instance_uuid], None, None, None, False) + mock_get_ac.assert_not_called() + @mock.patch('nova.scheduler.utils.resources_from_request_spec') @mock.patch('nova.scheduler.client.report.SchedulerReportClient.' 'get_allocation_candidates')