diff --git a/nova/compute/api.py b/nova/compute/api.py index 4bcb52be9e22..3eeeb69a7b54 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -2374,9 +2374,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 2f0dcd32c05c..6553dc45981f 100644 --- a/nova/objects/build_request.py +++ b/nova/objects/build_request.py @@ -435,7 +435,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) @@ -448,6 +449,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 b097f59bcd00..e34109cd8931 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 25d73ddfc086..da9eefa059d7 100644 --- a/nova/tests/unit/compute/test_compute_api.py +++ b/nova/tests/unit/compute/test_compute_api.py @@ -4635,7 +4635,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]) @@ -4669,7 +4669,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]) @@ -4703,14 +4703,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, @@ -4805,7 +4806,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(cctxt, {'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'}, @@ -4822,7 +4823,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,