Add migration db and object pagination support.
This will be used by migration pagination API. Added sort_keys, sort_dirs, limit, marker kwargs to get_by_filters method of MigrationList object, also added them and change-since to db.migration_get_all_by_filters for migrations pagination support. We need ensure it will maintain a default sort order with older microversions. Part of blueprint add-pagination-and-change-since-for-migration-list Change-Id: I3bbd5b95ecf9d096e662592c9b2e6ad37382fb49
This commit is contained in:
parent
74deea4d8f
commit
971cbaee02
@ -568,9 +568,13 @@ def migration_get_in_progress_by_host_and_node(context, host, node):
|
||||
return IMPL.migration_get_in_progress_by_host_and_node(context, host, node)
|
||||
|
||||
|
||||
def migration_get_all_by_filters(context, filters):
|
||||
def migration_get_all_by_filters(context, filters, sort_keys=None,
|
||||
sort_dirs=None, limit=None, marker=None):
|
||||
"""Finds all migrations using the provided filters."""
|
||||
return IMPL.migration_get_all_by_filters(context, filters)
|
||||
return IMPL.migration_get_all_by_filters(context, filters,
|
||||
sort_keys=sort_keys,
|
||||
sort_dirs=sort_dirs,
|
||||
limit=limit, marker=marker)
|
||||
|
||||
|
||||
def migration_get_in_progress_by_instance(context, instance_uuid,
|
||||
|
@ -4391,8 +4391,17 @@ def migration_get_in_progress_by_instance(context, instance_uuid,
|
||||
|
||||
|
||||
@pick_context_manager_reader
|
||||
def migration_get_all_by_filters(context, filters):
|
||||
def migration_get_all_by_filters(context, filters,
|
||||
sort_keys=None, sort_dirs=None,
|
||||
limit=None, marker=None):
|
||||
if limit == 0:
|
||||
return []
|
||||
|
||||
query = model_query(context, models.Migration)
|
||||
if 'changes-since' in filters:
|
||||
changes_since = timeutils.normalize_time(filters['changes-since'])
|
||||
query = query. \
|
||||
filter(models.Migration.updated_at >= changes_since)
|
||||
if "status" in filters:
|
||||
status = filters["status"]
|
||||
status = [status] if isinstance(status, six.string_types) else status
|
||||
@ -4411,8 +4420,24 @@ def migration_get_all_by_filters(context, filters):
|
||||
hidden = filters["hidden"]
|
||||
query = query.filter(models.Migration.hidden == hidden)
|
||||
if "instance_uuid" in filters:
|
||||
uuid = filters["instance_uuid"]
|
||||
query = query.filter(models.Migration.instance_uuid == uuid)
|
||||
instance_uuid = filters["instance_uuid"]
|
||||
query = query.filter(models.Migration.instance_uuid == instance_uuid)
|
||||
if marker:
|
||||
try:
|
||||
marker = migration_get_by_uuid(context, marker)
|
||||
except exception.MigrationNotFound:
|
||||
raise exception.MarkerNotFound(marker=marker)
|
||||
if limit or marker or sort_keys or sort_dirs:
|
||||
# Default sort by desc(['created_at', 'id'])
|
||||
sort_keys, sort_dirs = process_sort_params(sort_keys, sort_dirs,
|
||||
default_dir='desc')
|
||||
return sqlalchemyutils.paginate_query(query,
|
||||
models.Migration,
|
||||
limit=limit,
|
||||
sort_keys=sort_keys,
|
||||
marker=marker,
|
||||
sort_dirs=sort_dirs).all()
|
||||
else:
|
||||
return query.all()
|
||||
|
||||
|
||||
|
@ -185,7 +185,9 @@ class MigrationList(base.ObjectListBase, base.NovaObject):
|
||||
# Version 1.2: Migration version 1.2
|
||||
# Version 1.3: Added a new function to get in progress migrations
|
||||
# for an instance.
|
||||
VERSION = '1.3'
|
||||
# Version 1.4: Added sort_keys, sort_dirs, limit, marker kwargs to
|
||||
# get_by_filters for migrations pagination support.
|
||||
VERSION = '1.4'
|
||||
|
||||
fields = {
|
||||
'objects': fields.ListOfObjectsField('Migration'),
|
||||
@ -214,8 +216,11 @@ class MigrationList(base.ObjectListBase, base.NovaObject):
|
||||
db_migrations)
|
||||
|
||||
@base.remotable_classmethod
|
||||
def get_by_filters(cls, context, filters):
|
||||
db_migrations = db.migration_get_all_by_filters(context, filters)
|
||||
def get_by_filters(cls, context, filters, sort_keys=None, sort_dirs=None,
|
||||
limit=None, marker=None):
|
||||
db_migrations = db.migration_get_all_by_filters(
|
||||
context, filters, sort_keys=sort_keys, sort_dirs=sort_dirs,
|
||||
limit=limit, marker=marker)
|
||||
return base.obj_make_list(context, cls(context), objects.Migration,
|
||||
db_migrations)
|
||||
|
||||
|
@ -1454,7 +1454,8 @@ class MigrationTestCase(test.TestCase):
|
||||
|
||||
def _create(self, status='migrating', source_compute='host1',
|
||||
source_node='a', dest_compute='host2', dest_node='b',
|
||||
system_metadata=None, migration_type=None, uuid=None):
|
||||
system_metadata=None, migration_type=None, uuid=None,
|
||||
created_at=None, updated_at=None):
|
||||
|
||||
values = {'host': source_compute}
|
||||
instance = db.instance_create(self.ctxt, values)
|
||||
@ -1466,6 +1467,10 @@ class MigrationTestCase(test.TestCase):
|
||||
'source_node': source_node, 'dest_compute': dest_compute,
|
||||
'dest_node': dest_node, 'instance_uuid': instance['uuid'],
|
||||
'migration_type': migration_type, 'uuid': uuid}
|
||||
if created_at:
|
||||
values['created_at'] = created_at
|
||||
if updated_at:
|
||||
values['updated_at'] = updated_at
|
||||
db.migration_create(self.ctxt, values)
|
||||
return values
|
||||
|
||||
@ -1699,6 +1704,74 @@ class MigrationTestCase(test.TestCase):
|
||||
db.migration_get_by_id_and_instance, self.ctxt,
|
||||
'500', '501')
|
||||
|
||||
def _create_3_migration_after_time(self, time=None):
|
||||
time = time or timeutils.utcnow()
|
||||
tmp_time = time + datetime.timedelta(days=1)
|
||||
after_1hour = datetime.timedelta(hours=1)
|
||||
self._create(uuid=uuidsentinel.uuid_time1, created_at=tmp_time,
|
||||
updated_at=tmp_time + after_1hour)
|
||||
tmp_time = time + datetime.timedelta(days=2)
|
||||
self._create(uuid=uuidsentinel.uuid_time2, created_at=tmp_time,
|
||||
updated_at=tmp_time + after_1hour)
|
||||
tmp_time = time + datetime.timedelta(days=3)
|
||||
self._create(uuid=uuidsentinel.uuid_time3, created_at=tmp_time,
|
||||
updated_at=tmp_time + after_1hour)
|
||||
|
||||
def test_get_migrations_by_filters_with_limit(self):
|
||||
migrations = db.migration_get_all_by_filters(self.ctxt, {}, limit=3)
|
||||
self.assertEqual(3, len(migrations))
|
||||
|
||||
def test_get_migrations_by_filters_with_limit_marker(self):
|
||||
self._create_3_migration_after_time()
|
||||
# order by created_at, desc: time3, time2, time1
|
||||
migrations = db.migration_get_all_by_filters(
|
||||
self.ctxt, {}, limit=2, marker=uuidsentinel.uuid_time3)
|
||||
# time3 as marker: time2, time1
|
||||
self.assertEqual(2, len(migrations))
|
||||
self.assertEqual(migrations[0]['uuid'], uuidsentinel.uuid_time2)
|
||||
self.assertEqual(migrations[1]['uuid'], uuidsentinel.uuid_time1)
|
||||
# time3 as marker, limit 2: time3, time2
|
||||
migrations = db.migration_get_all_by_filters(
|
||||
self.ctxt, {}, limit=1, marker=uuidsentinel.uuid_time3)
|
||||
self.assertEqual(1, len(migrations))
|
||||
self.assertEqual(migrations[0]['uuid'], uuidsentinel.uuid_time2)
|
||||
|
||||
def test_get_migrations_by_filters_with_limit_marker_sort(self):
|
||||
self._create_3_migration_after_time()
|
||||
# order by created_at, desc: time3, time2, time1
|
||||
migrations = db.migration_get_all_by_filters(
|
||||
self.ctxt, {}, limit=2, marker=uuidsentinel.uuid_time3)
|
||||
# time2, time1
|
||||
self.assertEqual(2, len(migrations))
|
||||
self.assertEqual(migrations[0]['uuid'], uuidsentinel.uuid_time2)
|
||||
self.assertEqual(migrations[1]['uuid'], uuidsentinel.uuid_time1)
|
||||
|
||||
# order by updated_at, desc: time1, time2, time3
|
||||
migrations = db.migration_get_all_by_filters(
|
||||
self.ctxt, {}, sort_keys=['updated_at'], sort_dirs=['asc'],
|
||||
limit=2, marker=uuidsentinel.uuid_time1)
|
||||
# time2, time3
|
||||
self.assertEqual(2, len(migrations))
|
||||
self.assertEqual(migrations[0]['uuid'], uuidsentinel.uuid_time2)
|
||||
self.assertEqual(migrations[1]['uuid'], uuidsentinel.uuid_time3)
|
||||
|
||||
def test_get_migrations_by_filters_with_not_found_marker(self):
|
||||
self.assertRaises(exception.MarkerNotFound,
|
||||
db.migration_get_all_by_filters, self.ctxt, {},
|
||||
marker=uuidsentinel.not_found_marker)
|
||||
|
||||
def test_get_migrations_by_filters_with_changes_since(self):
|
||||
changes_time = timeutils.utcnow(with_timezone=True)
|
||||
self._create_3_migration_after_time(changes_time)
|
||||
after_1day_2hours = datetime.timedelta(days=1, hours=2)
|
||||
filters = {"changes-since": changes_time + after_1day_2hours}
|
||||
migrations = db.migration_get_all_by_filters(
|
||||
self.ctxt, filters,
|
||||
sort_keys=['updated_at'], sort_dirs=['asc'])
|
||||
self.assertEqual(2, len(migrations))
|
||||
self.assertEqual(migrations[0]['uuid'], uuidsentinel.uuid_time2)
|
||||
self.assertEqual(migrations[1]['uuid'], uuidsentinel.uuid_time3)
|
||||
|
||||
|
||||
class ModelsObjectComparatorMixin(object):
|
||||
def _dict_from_object(self, obj, ignored_keys):
|
||||
|
@ -215,7 +215,9 @@ class _TestMigrationObject(object):
|
||||
self.assertEqual(2, len(migrations))
|
||||
for index, db_migration in enumerate(db_migrations):
|
||||
self.compare_obj(migrations[index], db_migration)
|
||||
mock_get.assert_called_once_with(ctxt, filters)
|
||||
mock_get.assert_called_once_with(ctxt, filters,
|
||||
sort_dirs=None, sort_keys=None,
|
||||
limit=None, marker=None)
|
||||
|
||||
def test_migrate_old_resize_record(self):
|
||||
db_migration = dict(fake_db_migration(), migration_type=None)
|
||||
|
@ -1125,7 +1125,7 @@ object_data = {
|
||||
'MemoryDiagnostics': '1.0-2c995ae0f2223bb0f8e523c5cc0b83da',
|
||||
'Migration': '1.5-48bebaada664ee15bc23b35b2b814d75',
|
||||
'MigrationContext': '1.1-9fb17b0b521370957a884636499df52d',
|
||||
'MigrationList': '1.3-55595bfc1a299a5962614d0821a3567e',
|
||||
'MigrationList': '1.4-983a9c29d4f1e747ce719dc9063b729b',
|
||||
'MonitorMetric': '1.1-53b1db7c4ae2c531db79761e7acc52ba',
|
||||
'MonitorMetricList': '1.1-15ecf022a68ddbb8c2a6739cfc9f8f5e',
|
||||
'NicDiagnostics': '1.0-895e9ad50e0f56d5258585e3e066aea5',
|
||||
|
Loading…
Reference in New Issue
Block a user