Make pagination tolerate a deleted marker

Currently, Nova does not paginate correctly if the marker is
a deleted server. When trying to get servers with such a
marker, a "BadRequest" error saying that the marker is
not found will be raised.

We now always pass read_deleted=yes if a marker is being used.

Change-Id: I79a1fb79a38ac4006db622590574308aafdcb5b5
Closes-bug: #1481812
Related-Bug: #1398086
(cherry picked from commit 901c223f35)
This commit is contained in:
Martin Schuppert 2015-08-05 17:10:14 +02:00
parent d8bb068e50
commit 8fccffda59
2 changed files with 21 additions and 5 deletions

View File

@ -2079,13 +2079,9 @@ def instance_get_all_by_filters_sort(context, filters, limit=None, marker=None,
# paginate query
if marker is not None:
try:
if deleted:
marker = _instance_get_by_uuid(
marker = _instance_get_by_uuid(
context.elevated(read_deleted='yes'), marker,
session=session)
else:
marker = _instance_get_by_uuid(context,
marker, session=session)
except exception.InstanceNotFound:
raise exception.MarkerNotFound(marker)
try:

View File

@ -1000,6 +1000,18 @@ class SqlAlchemyDbApiNoDbTestCase(test.NoDBTestCase):
CONF.api_database)
mock_facade.get_session.assert_called_once_with()
@mock.patch.object(sqlalchemy_api, '_instance_get_by_uuid')
@mock.patch.object(sqlalchemy_api, '_instances_fill_metadata')
@mock.patch('oslo_db.sqlalchemy.utils.paginate_query')
def test_instance_get_all_by_filters_paginated_allows_deleted_marker(
self, mock_paginate, mock_fill, mock_get):
ctxt = mock.MagicMock()
ctxt.elevated.return_value = mock.sentinel.elevated
sqlalchemy_api.instance_get_all_by_filters_sort(ctxt, {}, marker='foo')
mock_get.assert_called_once_with(mock.sentinel.elevated,
'foo', session=mock.ANY)
ctxt.elevated.assert_called_once_with(read_deleted='yes')
class SqlAlchemyDbApiTestCase(DbTestCase):
def test_instance_get_all_by_host(self):
@ -2109,6 +2121,14 @@ class InstanceTestCase(test.TestCase, ModelsObjectComparatorMixin):
changes_since})
self._assertEqualListsOfInstances([i2], result)
db.instance_destroy(self.ctxt, i1['uuid'])
filters = {}
filters['changes-since'] = changes_since
filters['marker'] = i1['uuid']
result = db.instance_get_all_by_filters(self.ctxt,
filters)
self._assertEqualListsOfInstances([i2], result)
def test_instance_get_all_by_filters_exact_match(self):
instance = self.create_instance_with_args(host='host1')
self.create_instance_with_args(host='host12')