diff --git a/nova/compute/api.py b/nova/compute/api.py index 36de3abc3419..6f1371b45f45 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -2455,9 +2455,17 @@ class API(base.Base): # [sorted instances with no host] + [sorted instances with host]. # This means BuildRequest and cell0 instances first, then cell # instances - build_requests = objects.BuildRequestList.get_by_filters( - context, filters, limit=limit, marker=marker, sort_keys=sort_keys, - sort_dirs=sort_dirs) + try: + build_requests = objects.BuildRequestList.get_by_filters( + context, filters, limit=limit, marker=marker, + sort_keys=sort_keys, sort_dirs=sort_dirs) + # If we found the marker in we need to set it to None + # so we don't expect to find it in the cells below. + marker = None + except exception.MarkerNotFound: + # If we didn't find the marker in the build requests then keep + # looking for it in the cells. + build_requests = objects.BuildRequestList() build_req_instances = objects.InstanceList( objects=[build_req.instance for build_req in build_requests]) # Only subtract from limit if it is not None diff --git a/nova/objects/build_request.py b/nova/objects/build_request.py index 86a4de1d0f5a..566c349c12db 100644 --- a/nova/objects/build_request.py +++ b/nova/objects/build_request.py @@ -387,7 +387,8 @@ class BuildRequestList(base.ObjectListBase, base.NovaObject): filtered_build_reqs.append(build_req) - if (len(filtered_build_reqs) < 2) or (not sort_keys): + if (((len(filtered_build_reqs) < 2) or (not sort_keys)) + and not marker): # No need to sort return cls(context, objects=filtered_build_reqs) @@ -400,6 +401,8 @@ class BuildRequestList(base.ObjectListBase, base.NovaObject): if build_req.instance.uuid == marker: marker_index = i break + else: + raise exception.MarkerNotFound(marker=marker) len_build_reqs = len(sorted_build_reqs) limit_index = len_build_reqs if limit: diff --git a/nova/tests/functional/db/test_build_request.py b/nova/tests/functional/db/test_build_request.py index c3a60f0e1bf9..d65ab41fff3b 100644 --- a/nova/tests/functional/db/test_build_request.py +++ b/nova/tests/functional/db/test_build_request.py @@ -526,6 +526,13 @@ class BuildRequestListTestCase(test.NoDBTestCase): objects.base.obj_equal_prims(req.instance, req_list[i].instance) + def test_get_by_filters_marker_not_found(self): + self._create_req() + self.assertRaises(exception.MarkerNotFound, + build_request.BuildRequestList.get_by_filters, + self.context, {}, marker=uuidutils.generate_uuid(), + sort_keys=['id'], sort_dirs=['asc']) + def test_get_by_filters_limit(self): reqs = [self._create_req(), self._create_req(), diff --git a/nova/tests/unit/compute/test_compute_api.py b/nova/tests/unit/compute/test_compute_api.py index 630bc66a4369..56c80eed04ca 100644 --- a/nova/tests/unit/compute/test_compute_api.py +++ b/nova/tests/unit/compute/test_compute_api.py @@ -4575,7 +4575,7 @@ class _ComputeAPIUnitTestMixIn(object): self.context, {'foo': 'bar'}, limit=None, marker='fake-marker', sort_keys=['baz'], sort_dirs=['desc']) mock_inst_get.assert_called_once_with( - self.context, {'foo': 'bar'}, limit=None, marker='fake-marker', + self.context, {'foo': 'bar'}, limit=None, marker=None, expected_attrs=None, sort_keys=['baz'], sort_dirs=['desc']) for i, instance in enumerate(build_req_instances + cell_instances): self.assertEqual(instance, instances[i]) @@ -4609,7 +4609,7 @@ class _ComputeAPIUnitTestMixIn(object): self.context, {'foo': 'bar'}, limit=None, marker='fake-marker', sort_keys=['baz'], sort_dirs=['desc']) mock_inst_get.assert_called_once_with( - self.context, {'foo': 'bar'}, limit=None, marker='fake-marker', + self.context, {'foo': 'bar'}, limit=None, marker=None, expected_attrs=None, sort_keys=['baz'], sort_dirs=['desc']) for i, instance in enumerate(build_req_instances + cell_instances): self.assertEqual(instance, instances[i]) @@ -4643,14 +4643,15 @@ class _ComputeAPIUnitTestMixIn(object): self.context, {'foo': 'bar'}, limit=10, marker='fake-marker', sort_keys=['baz'], sort_dirs=['desc']) mock_inst_get.assert_called_once_with( - self.context, {'foo': 'bar'}, limit=8, marker='fake-marker', + self.context, {'foo': 'bar'}, limit=8, marker=None, expected_attrs=None, sort_keys=['baz'], sort_dirs=['desc']) for i, instance in enumerate(build_req_instances + cell_instances): self.assertEqual(instance, instances[i]) @mock.patch.object(context, 'target_cell') @mock.patch.object(objects.BuildRequestList, 'get_by_filters', - return_value=objects.BuildRequestList(objects=[])) + side_effect=exception.MarkerNotFound( + marker='fake-marker')) @mock.patch.object(objects.CellMapping, 'get_by_uuid') @mock.patch.object(objects.CellMappingList, 'get_all') def test_get_all_includes_cell0(self, mock_cm_get_all, @@ -4742,7 +4743,7 @@ class _ComputeAPIUnitTestMixIn(object): for cm in mock_cm_get_all.return_value: mock_target_cell.assert_any_call(self.context, cm) inst_get_calls = [mock.call(self.context, {'foo': 'bar'}, - limit=8, marker='fake-marker', + limit=8, marker=None, expected_attrs=None, sort_keys=['baz'], sort_dirs=['desc']), mock.call(mock.ANY, {'foo': 'bar'}, @@ -4759,7 +4760,8 @@ class _ComputeAPIUnitTestMixIn(object): @mock.patch.object(context, 'target_cell') @mock.patch.object(objects.BuildRequestList, 'get_by_filters', - return_value=objects.BuildRequestList(objects=[])) + side_effect=exception.MarkerNotFound( + marker=uuids.marker)) @mock.patch.object(objects.CellMapping, 'get_by_uuid') @mock.patch.object(objects.CellMappingList, 'get_all') def test_get_all_cell0_marker_not_found(self, mock_cm_get_all,