Fail heal_allocations if placement is borked

Following up on [1] to resolve the TODO, make nova-manage
heal_allocations fail fast if we can't talk to placement. (Note that the
existing behavior is preserved if we can talk to placement, but some
other error occurs retrieving allocations.)

[1] https://review.openstack.org/#/c/584599/21/nova/cmd/manage.py@1814

Change-Id: I1b79cc2c556fb06b8ffb8b9d6cabf980fa08a3aa
This commit is contained in:
Eric Fried 2018-08-28 15:53:39 -05:00
parent 176d1d90fd
commit b7aa6a3b93
2 changed files with 55 additions and 5 deletions

View File

@ -1808,10 +1808,12 @@ class PlacementCommands(object):
try:
allocations = placement.get_allocs_for_consumer(
ctxt, instance.uuid)
except (ks_exc.ClientException,
exception.ConsumerAllocationRetrievalFailed) as e:
except ks_exc.ClientException as e:
raise exception.AllocationUpdateFailed(
instance=instance.uuid,
error=_("Allocation retrieval failed: %s") % e)
except exception.ConsumerAllocationRetrievalFailed as e:
output(_("Allocation retrieval failed: %s") % e)
# TODO(mriedem): Fail fast here, since we can't talk to placement.
allocations = None
# get_allocations_for_consumer uses safe_connect which will

View File

@ -2481,7 +2481,7 @@ class TestNovaManagePlacement(test.NoDBTestCase):
uuid=uuidsentinel.instance, host='fake', node='fake',
task_state=None)]))
@mock.patch('nova.scheduler.client.report.SchedulerReportClient.'
'get_allocations_for_consumer', return_value={})
'get_allocs_for_consumer', return_value={})
@mock.patch('nova.objects.ComputeNode.get_by_host_and_nodename',
side_effect=exception.ComputeHostNotFound(host='fake'))
def test_heal_allocations_compute_host_not_found(
@ -2502,7 +2502,7 @@ class TestNovaManagePlacement(test.NoDBTestCase):
task_state=None, flavor=objects.Flavor(),
project_id='fake-project', user_id='fake-user')]))
@mock.patch('nova.scheduler.client.report.SchedulerReportClient.'
'get_allocations_for_consumer', return_value={})
'get_allocs_for_consumer', return_value={})
@mock.patch('nova.objects.ComputeNode.get_by_host_and_nodename',
return_value=objects.ComputeNode(uuid=uuidsentinel.node))
@mock.patch('nova.scheduler.utils.resources_from_flavor',
@ -2524,6 +2524,54 @@ class TestNovaManagePlacement(test.NoDBTestCase):
uuidsentinel.instance, mock.sentinel.resources, 'fake-project',
'fake-user')
@mock.patch('nova.objects.CellMappingList.get_all',
new=mock.Mock(return_value=objects.CellMappingList(objects=[
objects.CellMapping(name='cell1',
uuid=uuidsentinel.cell1)])))
@mock.patch('nova.objects.InstanceList.get_by_filters',
new=mock.Mock(return_value=objects.InstanceList(objects=[
objects.Instance(
uuid=uuidsentinel.instance, host='fake', node='fake',
task_state=None, flavor=objects.Flavor(),
project_id='fake-project', user_id='fake-user')])))
def test_heal_allocations_get_allocs_placement_fails(self):
self.assertEqual(3, self.cli.heal_allocations())
output = self.output.getvalue()
self.assertIn('Allocation retrieval failed', output)
# Having not mocked get_allocs_for_consumer, we get MissingAuthPlugin.
self.assertIn('An auth plugin is required', output)
@mock.patch('nova.objects.CellMappingList.get_all',
new=mock.Mock(return_value=objects.CellMappingList(objects=[
objects.CellMapping(name='cell1',
uuid=uuidsentinel.cell1)])))
@mock.patch('nova.objects.InstanceList.get_by_filters',
side_effect=[
objects.InstanceList(objects=[objects.Instance(
uuid=uuidsentinel.instance, host='fake', node='fake',
task_state=None, flavor=objects.Flavor(),
project_id='fake-project', user_id='fake-user')]),
objects.InstanceList(objects=[])])
@mock.patch('nova.scheduler.client.report.SchedulerReportClient.'
'get_allocs_for_consumer',
new=mock.Mock(
side_effect=exception.ConsumerAllocationRetrievalFailed(
consumer_uuid='CONSUMER', error='ERROR')))
@mock.patch('nova.objects.ComputeNode.get_by_host_and_nodename',
new=mock.Mock(
return_value=objects.ComputeNode(uuid=uuidsentinel.node)))
@mock.patch('nova.scheduler.utils.resources_from_flavor',
new=mock.Mock(return_value=mock.sentinel.resources))
@mock.patch('nova.scheduler.client.report.SchedulerReportClient.'
'put_allocations', return_value=True)
def test_heal_allocations_get_allocs_retrieval_fails(self, mock_put,
mock_getinst):
# This "succeeds"
self.assertEqual(0, self.cli.heal_allocations())
# We're really just verifying that we got to the end
mock_put.assert_called_once()
self.assertEqual(2, mock_getinst.call_count)
@mock.patch('nova.objects.CellMappingList.get_all',
return_value=objects.CellMappingList(objects=[
objects.CellMapping(name='cell1',