Make servers api view load instance fault from proper cell

Right now with CellsV2 the servers api will fail to load the fault
for an instance because it does not target it to a particular cell.
This makes us look up the instance mapping and use it to target
loading of the fault.

Change-Id: Ic2df2c3cfa66a91bd20437f534287e770b85f51d
This commit is contained in:
Dan Smith
2016-12-05 12:21:51 -08:00
parent 53b46aa794
commit a9a2bca070
2 changed files with 45 additions and 2 deletions
+22 -2
View File
@@ -23,7 +23,10 @@ from nova.api.openstack import common
from nova.api.openstack.compute.views import addresses as views_addresses
from nova.api.openstack.compute.views import flavors as views_flavors
from nova.api.openstack.compute.views import images as views_images
from nova import context as nova_context
from nova import exception
from nova.i18n import _LW
from nova import objects
from nova.objects import base as obj_base
from nova import utils
@@ -260,9 +263,26 @@ class ViewBuilder(common.ViewBuilder):
}],
}
def _load_fault(self, request, instance):
try:
mapping = objects.InstanceMapping.get_by_instance_uuid(
request.environ['nova.context'], instance.uuid)
if mapping.cell_mapping is not None:
with nova_context.target_cell(instance._context,
mapping.cell_mapping):
return instance.fault
except exception.InstanceMappingNotFound:
pass
# NOTE(danms): No instance mapping at all, or a mapping with no cell,
# which means a legacy environment or instance.
return instance.fault
def _get_fault(self, request, instance):
# This can result in a lazy load of the fault information
fault = instance.fault
if 'fault' in instance:
fault = instance.fault
else:
fault = self._load_fault(request, instance)
if not fault:
return None
@@ -4049,6 +4049,29 @@ class ServersViewBuilderTest(test.TestCase):
self.assertThat(output['server']['fault'],
matchers.DictMatches(expected_fault))
@mock.patch('nova.objects.InstanceMapping.get_by_instance_uuid')
def test_build_server_detail_with_fault_no_instance_mapping(self,
mock_im):
self.instance['vm_state'] = vm_states.ERROR
mock_im.side_effect = exception.InstanceMappingNotFound(uuid='foo')
self.request.context = context.RequestContext('fake', 'fake')
self.view_builder.show(self.request, self.instance)
mock_im.assert_called_once_with(mock.ANY, self.uuid)
@mock.patch('nova.objects.InstanceMapping.get_by_instance_uuid')
def test_build_server_detail_with_fault_loaded(self, mock_im):
self.instance['vm_state'] = vm_states.ERROR
fault = fake_instance.fake_fault_obj(self.request.context,
self.uuid, code=500,
message="No valid host was found")
self.instance['fault'] = fault
self.request.context = context.RequestContext('fake', 'fake')
self.view_builder.show(self.request, self.instance)
self.assertFalse(mock_im.called)
def test_build_server_detail_with_fault_no_details_not_admin(self):
self.instance['vm_state'] = vm_states.ERROR
self.instance['fault'] = fake_instance.fake_fault_obj(