diff --git a/nova/compute/api.py b/nova/compute/api.py index 031587db99bc..b86a16cbb54d 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -4524,13 +4524,13 @@ class HostAPI(base.Base): # and we should always iterate over the cells. However, certain # callers need the legacy behavior for now. if all_cells: - load_cells() services = [] - for cell in CELLS: - with nova_context.target_cell(context, cell) as cctxt: - cell_services = objects.ServiceList.get_all( - cctxt, disabled, set_zones=set_zones) - services.extend(cell_services) + service_dict = nova_context.scatter_gather_all_cells(context, + objects.ServiceList.get_all, disabled, set_zones=set_zones) + for service in service_dict.values(): + if service not in (nova_context.did_not_respond_sentinel, + nova_context.raised_exception_sentinel): + services.extend(service) else: services = objects.ServiceList.get_all(context, disabled, set_zones=set_zones) diff --git a/nova/tests/unit/compute/test_host_api.py b/nova/tests/unit/compute/test_host_api.py index a0fe540c0f67..1c06a1658aa9 100644 --- a/nova/tests/unit/compute/test_host_api.py +++ b/nova/tests/unit/compute/test_host_api.py @@ -186,6 +186,19 @@ class ComputeHostAPITestCase(test.TestCase): self.assertEqual(sorted(['host-%s' % cell.uuid for cell in cells]), sorted([svc.host for svc in services])) + @mock.patch('nova.context.scatter_gather_cells') + def test_service_get_all_cells_with_failures(self, mock_sg): + service = objects.Service(binary='nova-compute', + host='host-%s' % uuids.cell1) + mock_sg.return_value = { + uuids.cell1: [service], + uuids.cell2: context.raised_exception_sentinel + } + services = self.host_api.service_get_all(self.ctxt, all_cells=True) + # returns the results from cell1 and ignores cell2. + self.assertEqual(['host-%s' % uuids.cell1], + [svc.host for svc in services]) + def test_service_get_all_no_zones(self): services = [dict(test_service.fake_service, id=1, topic='compute', host='host1'), @@ -508,6 +521,10 @@ class ComputeHostAPICellsTestCase(ComputeHostAPITestCase): def test_service_get_all_cells(self): pass + @testtools.skip('cellsv1 does not use this') + def test_service_get_all_cells_with_failures(self): + pass + @testtools.skip('cellsv1 does not use this') def test_service_delete_ambiguous(self): pass