From 7e3a528b3551ced5fdf7387dea06fff5c63c8f32 Mon Sep 17 00:00:00 2001 From: Fengqian Gao Date: Mon, 19 Aug 2013 10:45:38 +0800 Subject: [PATCH] Add pagination parameter to the database backends of storage Put all parameters for pagination into class named pagination, add this paramter to the interface of the database driver. For now, the methods support pagination query include get_resources, get_meters, get_alarms. For get_samples function, because it has parameter limit now, which should be include in pagination class, it is hard to add the pagination query in this patch(it involves API codes). We will add that in another patch. Pagination parameter includes the following members: 1) 'limit': maximum number of items to return. 2) 'primary_sort_dir': sort direction of primary key. 2) 'marker_value': value of the primary key to identify the last item of the previous page. 3) 'sort_keys': array of attributes user pass in except the primary key. 4) 'sort_dirs': per-column array of sort_dirs, corresponding to sort_keys. We update the prototype of sqlalchemy, hbase, mongodb db2 and logging storage backend. Pagination query for mongodb is merged already, we need to reverse it first. It is part of bp/paginate-db-search. Implements blueprint paginate-db-search Change-Id: I6eedcd728427f4ab20f575aa10675822301fd472 --- ceilometer/storage/base.py | 31 ++++- ceilometer/storage/impl_db2.py | 33 ++---- ceilometer/storage/impl_hbase.py | 25 ++-- ceilometer/storage/impl_log.py | 8 +- ceilometer/storage/impl_mongodb.py | 65 +++-------- ceilometer/storage/impl_sqlalchemy.py | 36 ++---- tests/storage/test_storage_scenarios.py | 144 +++++++++++------------- 7 files changed, 138 insertions(+), 204 deletions(-) diff --git a/ceilometer/storage/base.py b/ceilometer/storage/base.py index e6f24c0c8..d81fefcd5 100644 --- a/ceilometer/storage/base.py +++ b/ceilometer/storage/base.py @@ -79,6 +79,29 @@ class NoResultFound(Exception): pass +class Pagination(object): + """Class for pagination query.""" + + def __init__(self, limit=None, primary_sort_dir='desc', sort_keys=[], + sort_dirs=[], marker_value=None): + """This puts all parameters used for paginate query together. + + :param limit: Maximum number of items to return; + :param primary_sort_dir: Sort direction of primary key. + :param marker_value: Value of primary key to identify the last item of + the previous page. + :param sort_keys: Array of attributes passed in by users to sort the + results besides the primary key. + :param sort_dirs: Per-column array of sort_dirs, corresponding to + sort_keys. + """ + self.limit = limit + self.primary_sort_dir = primary_sort_dir + self.marker_value = marker_value + self.sort_keys = sort_keys + self.sort_dirs = sort_dirs + + class StorageEngine(object): """Base class for storage engines.""" @@ -139,7 +162,7 @@ class Connection(object): def get_resources(self, user=None, project=None, source=None, start_timestamp=None, start_timestamp_op=None, end_timestamp=None, end_timestamp_op=None, - metaquery={}, resource=None): + metaquery={}, resource=None, pagination=None): """Return an iterable of models.Resource instances containing resource information. @@ -152,11 +175,12 @@ class Connection(object): :param end_timestamp_op: Optional timestamp end range operation. :param metaquery: Optional dict with metadata to match on. :param resource: Optional resource filter. + :param pagination: Optional pagination query. """ @abc.abstractmethod def get_meters(self, user=None, project=None, resource=None, source=None, - metaquery={}): + metaquery={}, pagination=None): """Return an iterable of model.Meter instances containing meter information. @@ -165,6 +189,7 @@ class Connection(object): :param resource: Optional resource filter. :param source: Optional source filter. :param metaquery: Optional dict with metadata to match on. + :param pagination: Optional pagination query. """ @abc.abstractmethod @@ -184,7 +209,7 @@ class Connection(object): @abc.abstractmethod def get_alarms(self, name=None, user=None, - project=None, enabled=True, alarm_id=None): + project=None, enabled=True, alarm_id=None, pagination=None): """Yields a lists of alarms that match filters """ diff --git a/ceilometer/storage/impl_db2.py b/ceilometer/storage/impl_db2.py index d7462ada0..7341d254e 100644 --- a/ceilometer/storage/impl_db2.py +++ b/ceilometer/storage/impl_db2.py @@ -340,8 +340,7 @@ class Connection(base.Connection): def get_resources(self, user=None, project=None, source=None, start_timestamp=None, start_timestamp_op=None, end_timestamp=None, end_timestamp_op=None, - metaquery={}, resource=None, limit=None, - marker_pairs=None, sort_key=None, sort_dir=None): + metaquery={}, resource=None, pagination=None): """Return an iterable of models.Resource instances :param user: Optional ID for user that owns the resource. @@ -353,14 +352,10 @@ class Connection(base.Connection): :param end_timestamp_op: Optional end time operator, like lt, le. :param metaquery: Optional dict with metadata to match on. :param resource: Optional resource filter. - :param limit: Number of documents should be returned. - :param marker_pairs: Attribute-value pairs to identify the last item of - the previous page. - :param sort_key: Attribute by which results be sorted. - :param sort_dir: Direction with which results be sorted(asc, desc). + :param pagination: Optional pagination query. """ - if limit or marker_pairs or sort_key or sort_dir: + if pagination: raise NotImplementedError(_('Pagination not implemented')) q = {} @@ -412,8 +407,7 @@ class Connection(base.Connection): ) def get_meters(self, user=None, project=None, resource=None, source=None, - metaquery={}, limit=None, marker_pairs=None, - sort_key=None, sort_dir=None): + metaquery={}, pagination=None): """Return an iterable of models.Meter instances :param user: Optional ID for user that owns the resource. @@ -421,14 +415,10 @@ class Connection(base.Connection): :param resource: Optional resource filter. :param source: Optional source filter. :param metaquery: Optional dict with metadata to match on. - :param limit: Number of documents should be returned. - :param marker_pairs: Attribute-value pairs to identify the last item of - the previous page. - :param sort_key: Attribute by which results be sorted. - :param sort_dir: Direction with which results be sorted(asc, desc). + :param pagination: Optional pagination query. """ - if limit or marker_pairs or sort_key or sort_dir: + if pagination: raise NotImplementedError(_('Pagination not implemented')) q = {} @@ -552,8 +542,7 @@ class Connection(base.Connection): return matching_metadata def get_alarms(self, name=None, user=None, - project=None, enabled=True, alarm_id=None, limit=None, - marker_pairs=None, sort_key=None, sort_dir=None): + project=None, enabled=True, alarm_id=None, pagination=None): """Yields a lists of alarms that match filters :param user: Optional ID for user that owns the resource. :param project: Optional ID for project that owns the resource. @@ -561,14 +550,10 @@ class Connection(base.Connection): :param alarm_id: Optional alarm_id to return one alarm. :param metaquery: Optional dict with metadata to match on. :param resource: Optional resource filter. - :param limit: Number of documents should be returned. - :param marker_pairs: Attribute-value pairs to identify the last item of - the previous page. - :param sort_key: Attribute by which results be sorted. - :param sort_dir: Direction with which results be sorted(asc, desc). + :param pagination: Optional pagination query. """ - if limit or marker_pairs or sort_key or sort_dir: + if pagination: raise NotImplementedError(_('Pagination not implemented')) q = {} diff --git a/ceilometer/storage/impl_hbase.py b/ceilometer/storage/impl_hbase.py index e69a1f128..5f5510ed8 100644 --- a/ceilometer/storage/impl_hbase.py +++ b/ceilometer/storage/impl_hbase.py @@ -283,8 +283,7 @@ class Connection(base.Connection): def get_resources(self, user=None, project=None, source=None, start_timestamp=None, start_timestamp_op=None, end_timestamp=None, end_timestamp_op=None, - metaquery={}, resource=None, limit=None, - marker_pairs=None, sort_key=None, sort_dir=None): + metaquery={}, resource=None, pagination=None): """Return an iterable of models.Resource instances :param user: Optional ID for user that owns the resource. @@ -296,14 +295,10 @@ class Connection(base.Connection): :param end_timestamp_op: Optional end time operator, like lt, le. :param metaquery: Optional dict with metadata to match on. :param resource: Optional resource filter. - :param limit: Number of documents should be returned. - :param marker_pairs: Attribute-value pairs to identify the last item of - the previous page. - :param sort_key: Attribute by which results be sorted. - :param sort_dir: Direction with which results be sorted(asc, desc). + :param pagination: Optional pagination query. """ - if limit or marker_pairs or sort_key or sort_dir: + if pagination: raise NotImplementedError(_('Pagination not implemented')) def make_resource(data, first_ts, last_ts): @@ -373,8 +368,7 @@ class Connection(base.Connection): resources[data['f:resource_id']][1]) def get_meters(self, user=None, project=None, resource=None, source=None, - metaquery={}, limit=None, marker_pairs=None, - sort_key=None, sort_dir=None): + metaquery={}, pagination=None): """Return an iterable of models.Meter instances :param user: Optional ID for user that owns the resource. @@ -382,14 +376,10 @@ class Connection(base.Connection): :param resource: Optional resource filter. :param source: Optional source filter. :param metaquery: Optional dict with metadata to match on. - :param limit: Number of documents should be returned. - :param marker_pairs: Attribute-value pairs to identify the last item of - the previous page. - :param sort_key: Attribute by which results be sorted. - :param sort_dir: Direction with which results be sorted(asc, desc). + :param pagination: Optional pagination query. """ - if limit or marker_pairs or sort_key or sort_dir: + if pagination: raise NotImplementedError(_('Pagination not implemented')) resource_table = self.conn.table(self.RESOURCE_TABLE) @@ -592,8 +582,7 @@ class Connection(base.Connection): return results def get_alarms(self, name=None, user=None, - project=None, enabled=True, alarm_id=None, limit=None, - marker_pairs=None, sort_key=None, sort_dir=None): + project=None, enabled=True, alarm_id=None, pagination=None): """Yields a lists of alarms that match filters raise NotImplementedError('metaquery not implemented') """ diff --git a/ceilometer/storage/impl_log.py b/ceilometer/storage/impl_log.py index 2ae0553b9..3ab999e46 100644 --- a/ceilometer/storage/impl_log.py +++ b/ceilometer/storage/impl_log.py @@ -84,7 +84,7 @@ class Connection(base.Connection): def get_resources(self, user=None, project=None, source=None, start_timestamp=None, start_timestamp_op=None, end_timestamp=None, end_timestamp_op=None, - metaquery={}, resource=None): + metaquery={}, resource=None, pagination=None): """Return an iterable of dictionaries containing resource information. { 'resource_id': UUID of the resource, @@ -104,11 +104,12 @@ class Connection(base.Connection): :param end_timestamp_op: Optional end time operator, like lt, le. :param metaquery: Optional dict with metadata to match on. :param resource: Optional resource filter. + :param pagination: Optional pagination query. """ return [] def get_meters(self, user=None, project=None, resource=None, source=None, - limit=None, metaquery={}): + limit=None, metaquery={}, pagination=None): """Return an iterable of dictionaries containing meter information. { 'name': name of the meter, @@ -124,6 +125,7 @@ class Connection(base.Connection): :param source: Optional source filter. :param limit: Maximum number of results to return. :param metaquery: Optional dict with metadata to match on. + :param pagination: Optional pagination query. """ return [] @@ -156,7 +158,7 @@ class Connection(base.Connection): return [] def get_alarms(self, name=None, user=None, - project=None, enabled=True, alarm_id=None): + project=None, enabled=True, alarm_id=None, pagination=None): """Yields a lists of alarms that match filters """ return [] diff --git a/ceilometer/storage/impl_mongodb.py b/ceilometer/storage/impl_mongodb.py index 53119dd51..ef32b6393 100644 --- a/ceilometer/storage/impl_mongodb.py +++ b/ceilometer/storage/impl_mongodb.py @@ -36,6 +36,7 @@ from ceilometer.openstack.common import log from ceilometer import storage from ceilometer.storage import base from ceilometer.storage import models +from ceilometer.openstack.common.gettextutils import _ cfg.CONF.import_opt('time_to_live', 'ceilometer.storage', group="database") @@ -560,8 +561,7 @@ class Connection(base.Connection): def get_resources(self, user=None, project=None, source=None, start_timestamp=None, start_timestamp_op=None, end_timestamp=None, end_timestamp_op=None, - metaquery={}, resource=None, limit=None, - marker_pairs=None, sort_key=None, sort_dir=None): + metaquery={}, resource=None, pagination=None): """Return an iterable of models.Resource instances :param user: Optional ID for user that owns the resource. @@ -573,16 +573,10 @@ class Connection(base.Connection): :param end_timestamp_op: Optional end time operator, like lt, le. :param metaquery: Optional dict with metadata to match on. :param resource: Optional resource filter. - :param limit: Number of documents should be returned. - :param marker_pairs: Attribute-value pairs to identify the last item of - the previous page. - :param sort_key: Attribute by which results be sorted. - :param sort_dir: Direction with which results be sorted(asc, desc). + :param pagination: Optional pagination query. """ - - if marker_pairs: - raise NotImplementedError( - "Cannot use marker pairs in resource listing, not implemented") + if pagination: + raise NotImplementedError(_('Pagination not implemented')) q = {} if user is not None: @@ -611,15 +605,8 @@ class Connection(base.Connection): if ts_range: q['timestamp'] = ts_range - sort_keys = base._handle_sort_key('resource', sort_key) - sort_instruction, query = self._build_paginate_query(None, - sort_keys, - sort_dir) - q.update(query) - aggregate = self.db.meter.aggregate([ {"$match": q}, - {"$sort": dict(sort_instruction)}, {"$group": { "_id": "$resource_id", "user_id": {"$first": "$user_id"}, @@ -635,10 +622,6 @@ class Connection(base.Connection): ]) for result in aggregate['result']: - if limit is not None: - if limit == 0: - break - limit -= 1 yield models.Resource( resource_id=result['_id'], user_id=result['user_id'], @@ -660,8 +643,7 @@ class Connection(base.Connection): ) def get_meters(self, user=None, project=None, resource=None, source=None, - metaquery={}, limit=None, marker_pairs=None, sort_key=None, - sort_dir=None): + metaquery={}, pagination=None): """Return an iterable of models.Meter instances :param user: Optional ID for user that owns the resource. @@ -669,12 +651,11 @@ class Connection(base.Connection): :param resource: Optional resource filter. :param source: Optional source filter. :param metaquery: Optional dict with metadata to match on. - :param limit: Number of documents should be returned. - :param marker_pairs: Attribute-value pairs to identify the last item of - the previous page. - :param sort_key: Attribute by which results be sorted. - :param sort_dir: Direction with which results be sorted(asc, desc). + :param pagination: Optional pagination query. """ + if pagination: + raise NotImplementedError(_('Pagination not implemented')) + q = {} if user is not None: q['user_id'] = user @@ -686,12 +667,7 @@ class Connection(base.Connection): q['source'] = source q.update(metaquery) - marker = self._get_marker(self.db.resource, marker_pairs=marker_pairs) - sort_keys = base._handle_sort_key('meter', sort_key) - - for r in self.paginate_query(q, self.db.resource, limit=limit, - marker=marker, - sort_keys=sort_keys, sort_dir=sort_dir): + for r in self.db.resource.find(q): for r_meter in r['meter']: yield models.Meter( name=r_meter['counter_name'], @@ -801,20 +777,18 @@ class Connection(base.Connection): return matching_metadata def get_alarms(self, name=None, user=None, - project=None, enabled=True, alarm_id=None, limit=None, - marker_pairs=None, sort_key=None, sort_dir=None): + project=None, enabled=True, alarm_id=None, pagination=None): """Yields a lists of alarms that match filters :param name: The Alarm name. :param user: Optional ID for user that owns the resource. :param project: Optional ID for project that owns the resource. :param enabled: Optional boolean to list disable alarm. :param alarm_id: Optional alarm_id to return one alarm. - :param limit: Number of rows should be returned. - :param marker_pairs: Attribute-value pairs to identify the last item of - the previous page. - :param sort_key: Attribute by which results be sorted. - :param sort_dir: Direction with which results be sorted(asc, desc). + :param pagination: Optional pagination query. """ + if pagination: + raise NotImplementedError(_('Pagination not implemented')) + q = {} if user is not None: q['user_id'] = user @@ -827,12 +801,7 @@ class Connection(base.Connection): if alarm_id is not None: q['alarm_id'] = alarm_id - marker = self._get_marker(self.db.alarm, marker_pairs=marker_pairs) - sort_keys = base._handle_sort_key('alarm', sort_key) - - for alarm in self.paginate_query(q, self.db.alarm, limit=limit, - marker=marker, sort_keys=sort_keys, - sort_dir=sort_dir): + for alarm in self.db.alarm.find(q): a = {} a.update(alarm) del a['_id'] diff --git a/ceilometer/storage/impl_sqlalchemy.py b/ceilometer/storage/impl_sqlalchemy.py index 526f29e8d..2743af898 100644 --- a/ceilometer/storage/impl_sqlalchemy.py +++ b/ceilometer/storage/impl_sqlalchemy.py @@ -273,8 +273,7 @@ class Connection(base.Connection): def get_resources(user=None, project=None, source=None, start_timestamp=None, start_timestamp_op=None, end_timestamp=None, end_timestamp_op=None, - metaquery={}, resource=None, limit=None, - marker_pairs=None, sort_key=None, sort_dir=None): + metaquery={}, resource=None, pagination=None): """Return an iterable of api_models.Resource instances :param user: Optional ID for user that owns the resource. @@ -286,14 +285,10 @@ class Connection(base.Connection): :param end_timestamp_op: Optional end time operator, like lt, le. :param metaquery: Optional dict with metadata to match on. :param resource: Optional resource filter. - :param limit: Number of documents should be returned. - :param marker_pairs: Attribute-value pairs to identify the last item of - the previous page. - :param sort_key: Attribute by which results be sorted. - :param sort_dir: Direction with which results be sorted(asc, desc). + :param pagination: Optional pagination query. """ - if limit or marker_pairs or sort_key or sort_dir: + if pagination: raise NotImplementedError(_('Pagination not implemented')) session = sqlalchemy_session.get_session() @@ -344,8 +339,7 @@ class Connection(base.Connection): @staticmethod def get_meters(user=None, project=None, resource=None, source=None, - metaquery={}, limit=None, marker_pairs=None, - sort_key=None, sort_dir=None): + metaquery={}, pagination=None): """Return an iterable of api_models.Meter instances :param user: Optional ID for user that owns the resource. @@ -353,14 +347,10 @@ class Connection(base.Connection): :param resource: Optional ID of the resource. :param source: Optional source filter. :param metaquery: Optional dict with metadata to match on. - :param limit: Number of documents should be returned. - :param marker_pairs: Attribute-value pairs to identify the last item of - the previous page. - :param sort_key: Attribute by which results be sorted. - :param sort_dir: Direction with which results be sorted(asc, desc). + :param pagination: Optional pagination query. """ - if limit or marker_pairs or sort_key or sort_dir: + if pagination: raise NotImplementedError(_('Pagination not implemented')) session = sqlalchemy_session.get_session() @@ -571,24 +561,16 @@ class Connection(base.Connection): repeat_actions=row.repeat_actions) def get_alarms(self, name=None, user=None, - project=None, enabled=True, alarm_id=None, - limit=None, marker_pairs=None, - sort_key=None, sort_dir=None): + project=None, enabled=True, alarm_id=None, pagination=None): """Yields a lists of alarms that match filters :param user: Optional ID for user that owns the resource. :param project: Optional ID for project that owns the resource. :param enabled: Optional boolean to list disable alarm. :param alarm_id: Optional alarm_id to return one alarm. - :param metaquery: Optional dict with metadata to match on. - :param resource: Optional resource filter. - :param limit: Number of documents should be returned. - :param marker_pairs: Attribute-value pairs to identify the last item of - the previous page. - :param sort_key: Attribute by which results be sorted. - :param sort_dir: Direction with which results be sorted(asc, desc). + :param pagination: Optional pagination query. """ - if limit or marker_pairs or sort_key or sort_dir: + if pagination: raise NotImplementedError(_('Pagination not implemented')) session = sqlalchemy_session.get_session() diff --git a/tests/storage/test_storage_scenarios.py b/tests/storage/test_storage_scenarios.py index 730e1604e..def8562aa 100644 --- a/tests/storage/test_storage_scenarios.py +++ b/tests/storage/test_storage_scenarios.py @@ -30,6 +30,7 @@ from ceilometer import sample from ceilometer import storage from ceilometer.tests import db as tests_db from ceilometer.storage import models +from ceilometer.storage.base import Pagination load_tests = testscenarios.load_tests_apply_scenarios @@ -340,41 +341,40 @@ class ResourceTestPagination(DBTestBase, tests_db.MixinTestsWithBackendScenarios): def test_get_resource_all_limit(self): - results = list(self.conn.get_resources(limit=8)) + pagination = Pagination(limit=8) + results = list(self.conn.get_resources(pagination=pagination)) self.assertEqual(len(results), 8) - results = list(self.conn.get_resources(limit=5)) + pagination = Pagination(limit=5) + results = list(self.conn.get_resources(pagination=pagination)) self.assertEqual(len(results), 5) def test_get_resources_all_marker(self): - marker_pairs = {'user_id': 'user-id-4', - 'project_id': 'project-id-4'} - results = list(self.conn.get_resources(marker_pairs=marker_pairs, - sort_key='user_id', - sort_dir='asc')) + pagination = Pagination(primary_sort_dir='asc', sort_keys=['user_id'], + sort_dirs=['asc'], + marker_value='resource-id-4') + results = list(self.conn.get_resources(pagination=pagination)) self.assertEqual(len(results), 5) def test_get_resources_paginate(self): - marker_pairs = {'user_id': 'user-id-4'} - results = self.conn.get_resources(limit=3, marker_pairs=marker_pairs, - sort_key='user_id', - sort_dir='asc') + pagination = Pagination(limit=3, primary_sort_dir='asc', + sort_keys=['user_id'], sort_dirs=['asc'], + marker_value='resource-id-4') + results = self.conn.get_resources(pagination=pagination) self.assertEqual(['user-id-5', 'user-id-6', 'user-id-7'], [i.user_id for i in results]) - marker_pairs = {'user_id': 'user-id-4'} - results = list(self.conn.get_resources(limit=2, - marker_pairs=marker_pairs, - sort_key='user_id', - sort_dir='desc')) + pagination = Pagination(limit=2, primary_sort_dir='desc', + sort_keys=['user_id'], sort_dirs=['asc'], + marker_value='resource-id-4') + results = list(self.conn.get_resources(pagination=pagination)) self.assertEqual(['user-id-3', 'user-id-2'], [i.user_id for i in results]) - marker_pairs = {'project_id': 'project-id-5'} - results = list(self.conn.get_resources(limit=3, - marker_pairs=marker_pairs, - sort_key='user_id', - sort_dir='asc')) + pagination = Pagination(limit=3, primary_sort_dir='asc', + sort_keys=['user_id'], sort_dirs=['asc'], + marker_value='resource-id-5') + results = list(self.conn.get_resources(pagination=pagination)) self.assertEqual(['resource-id-6', 'resource-id-7', 'resource-id-8'], [i.resource_id for i in results]) @@ -412,44 +412,48 @@ class MeterTestPagination(DBTestBase, tests_db.MixinTestsWithBackendScenarios): def tet_get_meters_all_limit(self): - results = list(self.conn.get_meters(limit=8)) + pagination = Pagination(limit=8) + results = list(self.conn.get_meters(pagination=pagination)) self.assertEqual(len(results), 8) - results = list(self.conn.get_meters(limit=5)) + pagination = Pagination(limit=5) + results = list(self.conn.get_meters(pagination=pagination)) self.assertEqual(len(results), 5) def test_get_meters_all_marker(self): - marker_pairs = {'user_id': 'user-id-alternate'} - results = list(self.conn.get_meters(marker_pairs=marker_pairs, - sort_key='user_id', - sort_dir='desc')) + pagination = Pagination(limit=3, primary_sort_dir='desc', + sort_keys=['user_id'], sort_dirs=['desc'], + marker_value='resource-id-5') + + results = list(self.conn.get_meters(pagination=pagination)) self.assertEqual(len(results), 8) def test_get_meters_paginate(self): - marker_pairs = {'user_id': 'user-id-alternate'} - results = self.conn.get_meters(limit=3, marker_pairs=marker_pairs, - sort_key='user_id', sort_dir='desc') + pagination = Pagination(limit=3, primary_sort_dir='desc', + sort_keys=['user_id'], sort_dirs=['desc'], + marker_value='resource-id-5') + results = self.conn.get_meters(pagination=pagination) self.assertEqual(['user-id-8', 'user-id-7', 'user-id-6'], [i.user_id for i in results]) - marker_pairs = {'user_id': 'user-id-4'} - results = self.conn.get_meters(limit=3, marker_pairs=marker_pairs, - sort_key='user_id', - sort_dir='asc') + pagination = Pagination(limit=3, primary_sort_dir='asc', + sort_keys=['user_id'], sort_dirs=['desc'], + marker_value='resource-id-5') + results = self.conn.get_meters(pagination=pagination) self.assertEqual(['user-id-5', 'user-id-6', 'user-id-7'], [i.user_id for i in results]) - marker_pairs = {'user_id': 'user-id-4'} - results = list(self.conn.get_meters(limit=2, - marker_pairs=marker_pairs, - sort_key='user_id', - sort_dir='desc')) + pagination = Pagination(limit=2, primary_sort_dir='desc', + sort_keys=['user_id'], sort_dirs=['desc'], + marker_value='resource-id-5') + results = list(self.conn.get_meters(pagination=pagination)) self.assertEqual(['user-id-3', 'user-id-2'], [i.user_id for i in results]) - marker_pairs = {'user_id': 'user-id'} - results = self.conn.get_meters(limit=3, marker_pairs=marker_pairs, - sort_key='user_id', sort_dir='desc') + pagination = Pagination(limit=3, primary_sort_dir='desc', + sort_keys=['user_id'], sort_dirs=['desc'], + marker_value='resource-id-5') + results = self.conn.get_meters(pagination=pagination) self.assertEqual([], [i.user_id for i in results]) @@ -1615,64 +1619,42 @@ class AlarmTestPagination(AlarmTestBase, def test_get_alarm_all_limit(self): self.add_some_alarms() - alarms = list(self.conn.get_alarms(limit=2)) + pagination = Pagination(limit=2) + alarms = list(self.conn.get_alarms(pagination=pagination)) self.assertEqual(len(alarms), 2) - alarms = list(self.conn.get_alarms(limit=1)) + pagination = Pagination(limit=1) + alarms = list(self.conn.get_alarms(pagination=pagination)) self.assertEqual(len(alarms), 1) def test_get_alarm_all_marker(self): self.add_some_alarms() - marker_pairs = {'name': 'orange-alert'} - alarms = list(self.conn.get_alarms(marker_pairs=marker_pairs, - sort_key='name', - sort_dir='desc')) + pagination = Pagination(marker_value='orange-alert') + alarms = list(self.conn.get_alarms(pagination=pagination)) self.assertEqual(len(alarms), 0) - marker_pairs = {'name': 'red-alert'} - alarms = list(self.conn.get_alarms(marker_pairs=marker_pairs, - sort_key='name', - sort_dir='desc')) + pagination = Pagination(marker_value='red-alert') + alarms = list(self.conn.get_alarms(pagination=pagination)) self.assertEqual(len(alarms), 1) - marker_pairs = {'name': 'yellow-alert'} - alarms = list(self.conn.get_alarms(marker_pairs=marker_pairs, - sort_key='name', - sort_dir='desc')) - self.assertEqual(len(alarms), 2) - - def test_get_alarm_sort_marker(self): - self.add_some_alarms() - - marker_pairs = {'name': 'orange-alert'} - alarms = list(self.conn.get_alarms(sort_key='counter_name', - sort_dir='desc', - marker_pairs=marker_pairs)) - self.assertEqual(len(alarms), 1) - - marker_pairs = {'name': 'yellow-alert'} - alarms = list(self.conn.get_alarms(sort_key='comparison_operator', - sort_dir='desc', - marker_pairs=marker_pairs)) + pagination = Pagination(marker_value='yellow-alert') + alarms = list(self.conn.get_alarms(pagination=pagination)) self.assertEqual(len(alarms), 2) def test_get_alarm_paginate(self): self.add_some_alarms() - marker_pairs = {'name': 'yellow-alert'} - page = list(self.conn.get_alarms(limit=4, - marker_pairs=marker_pairs, - sort_key='name', sort_dir='desc')) + pagination = Pagination(limit=4, marker_value='yellow-alert') + page = list(self.conn.get_alarms(pagination=pagination)) self.assertEqual(['red-alert', 'orange-alert'], [i.name for i in page]) - marker_pairs = {'name': 'orange-alert'} - page1 = list(self.conn.get_alarms(limit=2, - sort_key='comparison_operator', - sort_dir='desc', - marker_pairs=marker_pairs)) - self.assertEqual(['red-alert'], [i.name for i in page1]) + pagination = Pagination(limit=2, marker_value='orange-alert', + primary_sort_dir='asc') + page1 = list(self.conn.get_alarms(pagination=pagination)) + self.assertEqual(['red-alert', 'yellow-alert'], + [i.name for i in page1]) class EventTestBase(tests_db.TestBase,