Disable limit if affinity(anti)/same(different)host is requested

When max_placement_results is less than the total number of nodes in
a deployment it may not be possible to use the affinity, anti-affinity,
same host or different host filters as there is no guarantee
for placement to return the expected hosts under such situations. This
patch disables the max_placement_results parameter when nova queries
placement for ``GET /allocation_candidates`` if the
request_spec.scheduler_hints containts any of group, same_host or
different_host keys.

NOTE(mriedem): The test is modified to remove the to_querystring
call since change I496e8d64907fdcb0e2da255725aed1fc529725f2 that
added it was in Rocky. As such, assertResourceRequestsEqual is
changed to also assert the expected limit value.

Change-Id: Ia2d5f80b6db59a8f6da03344aeaa6aa599407672
Closes-Bug: #1827628
(cherry picked from commit 2f9e972ba3)
(cherry picked from commit c094a6ef0c)
(cherry picked from commit aa19788d78)
This commit is contained in:
Surya Seetharaman 2019-05-09 16:22:13 +02:00 committed by Matt Riedemann
parent 3dcefba60a
commit 472b999355
2 changed files with 41 additions and 0 deletions

View File

@ -343,6 +343,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

View File

@ -10,6 +10,7 @@
# License for the specific language governing permissions and limitations
# under the License.
import ddt
import mock
from nova.api.openstack.placement import lib as plib
@ -23,6 +24,7 @@ from nova.tests.unit import fake_instance
from nova.tests import uuidsentinel as uuids
@ddt.ddt
class TestUtils(test.NoDBTestCase):
def setUp(self):
@ -35,6 +37,7 @@ class TestUtils(test.NoDBTestCase):
self.assertEqual(set(ex_by_id), set(ob_by_id))
for ident in ex_by_id:
self.assertEqual(vars(ex_by_id[ident]), vars(ob_by_id[ident]))
self.assertEqual(expected._limit, observed._limit)
def _test_resources_from_request_spec(self, flavor, expected):
fake_spec = objects.RequestSpec(flavor=flavor)
@ -299,6 +302,38 @@ class TestUtils(test.NoDBTestCase):
resources = utils.resources_from_request_spec(fake_spec)
self.assertEqual(expected._limit, resources._limit)
@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] = plib.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)
@mock.patch('nova.compute.utils.is_volume_backed_instance',
return_value=False)
def test_resources_from_flavor_no_bfv(self, mock_is_bfv):