Skip to content

Commit 808d364

Browse files
committed
Raise MarkerNotFound if BuildRequestList.get_by_filters doesn't find marker
For some reason, probably because build requests are meant to be short lived and we don't get a lot of bugs about paging misbehavior, when paging instances with a marker, we didn't raise MarkerNotFound if we didn't find the marker in the list of build requests. Doing so would match what we do when paging over cells and listing instances using a marker. Once we find the marker, be that in build_requests, or one of the cells, we need to set the marker to None to stop looking for it elsewhere if we have more space to fill our limit. For example, see change I8a957bebfcecd6ac712103c346e028d80f1ecd7c. This patch fixes the issue by raising MarkerNotFound from BuildRequestList get_by_filters if there is a marker and we didn't find a build request for it. The compute API get_all() method handles that as normal and continues looking for the marker in one of the cells. Change-Id: I1aa3ca6cc70cef65d24dec1e7db9491c9b73f7ab Closes-Bug: #1737856 (cherry picked from commit 1706e39) (cherry picked from commit 344029b) (cherry picked from commit b00b2fe)
1 parent 506e4f5 commit 808d364

File tree

4 files changed

+31
-11
lines changed

4 files changed

+31
-11
lines changed

nova/compute/api.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2315,9 +2315,17 @@ def _remap_system_metadata_filter(metadata):
23152315
# [sorted instances with no host] + [sorted instances with host].
23162316
# This means BuildRequest and cell0 instances first, then cell
23172317
# instances
2318-
build_requests = objects.BuildRequestList.get_by_filters(
2319-
context, filters, limit=limit, marker=marker, sort_keys=sort_keys,
2320-
sort_dirs=sort_dirs)
2318+
try:
2319+
build_requests = objects.BuildRequestList.get_by_filters(
2320+
context, filters, limit=limit, marker=marker,
2321+
sort_keys=sort_keys, sort_dirs=sort_dirs)
2322+
# If we found the marker in we need to set it to None
2323+
# so we don't expect to find it in the cells below.
2324+
marker = None
2325+
except exception.MarkerNotFound:
2326+
# If we didn't find the marker in the build requests then keep
2327+
# looking for it in the cells.
2328+
build_requests = objects.BuildRequestList()
23212329
build_req_instances = objects.InstanceList(
23222330
objects=[build_req.instance for build_req in build_requests])
23232331
# Only subtract from limit if it is not None

nova/objects/build_request.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,8 @@ def get_by_filters(cls, context, filters, limit=None, marker=None,
370370

371371
filtered_build_reqs.append(build_req)
372372

373-
if (len(filtered_build_reqs) < 2) or (not sort_keys):
373+
if (((len(filtered_build_reqs) < 2) or (not sort_keys))
374+
and not marker):
374375
# No need to sort
375376
return cls(context, objects=filtered_build_reqs)
376377

@@ -383,6 +384,8 @@ def get_by_filters(cls, context, filters, limit=None, marker=None,
383384
if build_req.instance.uuid == marker:
384385
marker_index = i
385386
break
387+
else:
388+
raise exception.MarkerNotFound(marker=marker)
386389
len_build_reqs = len(sorted_build_reqs)
387390
limit_index = len_build_reqs
388391
if limit:

nova/tests/functional/db/test_build_request.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -526,6 +526,13 @@ def test_get_by_filters_marker(self):
526526
objects.base.obj_equal_prims(req.instance,
527527
req_list[i].instance)
528528

529+
def test_get_by_filters_marker_not_found(self):
530+
self._create_req()
531+
self.assertRaises(exception.MarkerNotFound,
532+
build_request.BuildRequestList.get_by_filters,
533+
self.context, {}, marker=uuidutils.generate_uuid(),
534+
sort_keys=['id'], sort_dirs=['asc'])
535+
529536
def test_get_by_filters_limit(self):
530537
reqs = [self._create_req(),
531538
self._create_req(),

nova/tests/unit/compute/test_compute_api.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4345,7 +4345,7 @@ def test_get_all_includes_build_requests(self, mock_cell_mapping_get,
43454345
self.context, {'foo': 'bar'}, limit=None, marker='fake-marker',
43464346
sort_keys=['baz'], sort_dirs=['desc'])
43474347
mock_inst_get.assert_called_once_with(
4348-
self.context, {'foo': 'bar'}, limit=None, marker='fake-marker',
4348+
self.context, {'foo': 'bar'}, limit=None, marker=None,
43494349
expected_attrs=None, sort_keys=['baz'], sort_dirs=['desc'])
43504350
for i, instance in enumerate(build_req_instances + cell_instances):
43514351
self.assertEqual(instance, instances[i])
@@ -4379,7 +4379,7 @@ def test_get_all_includes_build_requests_filter_dupes(self,
43794379
self.context, {'foo': 'bar'}, limit=None, marker='fake-marker',
43804380
sort_keys=['baz'], sort_dirs=['desc'])
43814381
mock_inst_get.assert_called_once_with(
4382-
self.context, {'foo': 'bar'}, limit=None, marker='fake-marker',
4382+
self.context, {'foo': 'bar'}, limit=None, marker=None,
43834383
expected_attrs=None, sort_keys=['baz'], sort_dirs=['desc'])
43844384
for i, instance in enumerate(build_req_instances + cell_instances):
43854385
self.assertEqual(instance, instances[i])
@@ -4413,14 +4413,15 @@ def test_get_all_build_requests_decrement_limit(self,
44134413
self.context, {'foo': 'bar'}, limit=10, marker='fake-marker',
44144414
sort_keys=['baz'], sort_dirs=['desc'])
44154415
mock_inst_get.assert_called_once_with(
4416-
self.context, {'foo': 'bar'}, limit=8, marker='fake-marker',
4416+
self.context, {'foo': 'bar'}, limit=8, marker=None,
44174417
expected_attrs=None, sort_keys=['baz'], sort_dirs=['desc'])
44184418
for i, instance in enumerate(build_req_instances + cell_instances):
44194419
self.assertEqual(instance, instances[i])
44204420

44214421
@mock.patch.object(context, 'target_cell')
44224422
@mock.patch.object(objects.BuildRequestList, 'get_by_filters',
4423-
return_value=objects.BuildRequestList(objects=[]))
4423+
side_effect=exception.MarkerNotFound(
4424+
marker='fake-marker'))
44244425
@mock.patch.object(objects.CellMapping, 'get_by_uuid')
44254426
def test_get_all_includes_cell0(self, mock_cell_mapping_get,
44264427
mock_buildreq_get, mock_target_cell):
@@ -4496,11 +4497,11 @@ def test_get_all_includes_build_request_cell0(self, mock_cell_mapping_get,
44964497
mock_target_cell.assert_called_once_with(self.context,
44974498
cell_mapping)
44984499
inst_get_calls = [mock.call(self.context, {'foo': 'bar'},
4499-
limit=8, marker='fake-marker',
4500+
limit=8, marker=None,
45004501
expected_attrs=None, sort_keys=['baz'],
45014502
sort_dirs=['desc']),
45024503
mock.call(self.context, {'foo': 'bar'},
4503-
limit=6, marker='fake-marker',
4504+
limit=6, marker=None,
45044505
expected_attrs=None, sort_keys=['baz'],
45054506
sort_dirs=['desc'])
45064507
]
@@ -4513,7 +4514,8 @@ def test_get_all_includes_build_request_cell0(self, mock_cell_mapping_get,
45134514

45144515
@mock.patch.object(context, 'target_cell')
45154516
@mock.patch.object(objects.BuildRequestList, 'get_by_filters',
4516-
return_value=objects.BuildRequestList(objects=[]))
4517+
side_effect=exception.MarkerNotFound(
4518+
marker=uuids.marker))
45174519
@mock.patch.object(objects.CellMapping, 'get_by_uuid')
45184520
def test_get_all_cell0_marker_not_found(self, mock_cell_mapping_get,
45194521
mock_buildreq_get,

0 commit comments

Comments
 (0)