Handle None returned from get_allocation_candidates due to connect failure

The get_allocation_candidates method is decorated with the safe_connect
decorator that handles any failures trying to connect to the Placement
service. If keystoneauth raises an exception, safe_connect will log it
and return None. The select_destinations() method in the SchedulerManager
needs to handle the None case so it doesn't assume a tuple is coming back
which would result in a TypeError.

Change-Id: Iffd72f51f25a9e874eaacf374d80794675236ac1
Closes-Bug: #1705141
This commit is contained in:
Matt Riedemann 2017-07-18 20:08:57 -04:00 committed by Jay Pipes
parent e6d47a8fd0
commit dcde535f95
2 changed files with 26 additions and 1 deletions

View File

@ -111,7 +111,10 @@ class SchedulerManager(manager.Manager):
alloc_reqs, p_sums = None, None
if self.driver.USES_ALLOCATION_CANDIDATES:
res = self.placement_client.get_allocation_candidates(resources)
alloc_reqs, p_sums = res
# We have to handle the case that we failed to connect to the
# Placement service and the safe_connect decorator on
# get_allocation_candidates returns None.
alloc_reqs, p_sums = res if res is not None else (None, None)
if not alloc_reqs:
LOG.debug("Got no allocation candidates from the Placement "
"API. This may be a temporary occurrence as compute "

View File

@ -127,6 +127,28 @@ class SchedulerManagerTestCase(test.NoDBTestCase):
[fake_spec.instance_uuid], None)
mock_get_ac.assert_called_once_with(mock_rfrs.return_value)
@mock.patch('nova.scheduler.utils.resources_from_request_spec')
@mock.patch('nova.scheduler.client.report.SchedulerReportClient.'
'get_allocation_candidates', return_value=None)
def test_select_destination_placement_connect_fails(
self, mock_get_ac, mock_rfrs):
"""Tests that we will pass None for the provider_summaries parameter to
the scheduler driver select_destinations() method when the scheduler
report client's get_allocation_candidates() returns None, which it
would if the connection to Placement failed and the safe_connect
decorator returns None.
"""
fake_spec = objects.RequestSpec()
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)
mock_get_ac.assert_called_once_with(mock_rfrs.return_value)
@mock.patch('nova.scheduler.utils.resources_from_request_spec')
@mock.patch('nova.scheduler.client.report.SchedulerReportClient.'
'get_allocation_candidates')