diff --git a/nova/scheduler/utils.py b/nova/scheduler/utils.py index 64c37e01467e..6dc966e6cf5a 100644 --- a/nova/scheduler/utils.py +++ b/nova/scheduler/utils.py @@ -491,6 +491,12 @@ def resources_from_request_spec(spec_obj): if 'force_nodes' in spec_obj and spec_obj.force_nodes: res_req._limit = None + # Don't limit allocation candidates when using affinity/anti-affinity. + if ('scheduler_hints' in spec_obj and any( + key in ['group', 'same_host', 'different_host'] + for key in spec_obj.scheduler_hints)): + res_req._limit = None + return res_req diff --git a/nova/tests/unit/scheduler/test_utils.py b/nova/tests/unit/scheduler/test_utils.py index 248be7af2ab0..a6fbdcf25ded 100644 --- a/nova/tests/unit/scheduler/test_utils.py +++ b/nova/tests/unit/scheduler/test_utils.py @@ -10,6 +10,7 @@ # License for the specific language governing permissions and limitations # under the License. +import ddt import mock from oslo_utils.fixture import uuidsentinel as uuids @@ -23,6 +24,7 @@ from nova.tests.unit import fake_instance from nova.tests.unit.scheduler import fakes +@ddt.ddt class TestUtils(test.NoDBTestCase): def setUp(self): @@ -490,6 +492,42 @@ class TestUtils(test.NoDBTestCase): req.get_request_group(None).resources) self.assertEqual(1, len(list(req.resource_groups()))) + @ddt.data( + # Test single hint that we are checking for. + {'group': [uuids.fake]}, + # Test hint we care about and some other random hint. + {'same_host': [uuids.fake], 'fake-hint': ['fake-value']}, + # Test multiple hints we are checking for. + {'same_host': [uuids.server1], 'different_host': [uuids.server2]}) + def test_resources_from_request_spec_no_limit_based_on_hint(self, hints): + """Tests that there is no limit applied to the + GET /allocation_candidates query string if a given scheduler hint + is in the request spec. + """ + flavor = objects.Flavor(vcpus=1, + memory_mb=1024, + root_gb=15, + ephemeral_gb=0, + swap=0) + fake_spec = objects.RequestSpec( + flavor=flavor, scheduler_hints=hints) + expected = utils.ResourceRequest() + expected._rg_by_id[None] = objects.RequestGroup( + use_same_provider=False, + resources={ + 'VCPU': 1, + 'MEMORY_MB': 1024, + 'DISK_GB': 15, + }, + ) + expected._limit = None + resources = utils.resources_from_request_spec(fake_spec) + self.assertResourceRequestsEqual(expected, resources) + expected_querystring = ( + 'resources=DISK_GB%3A15%2CMEMORY_MB%3A1024%2CVCPU%3A1' + ) + self.assertEqual(expected_querystring, resources.to_querystring()) + @mock.patch('nova.compute.utils.is_volume_backed_instance', return_value=False) def test_resources_from_flavor_no_bfv(self, mock_is_bfv):