Add instance action db and obj pagination support.

This will be used by instance action pagination API.

Add limit/marker/filters support to get_by_instance_uuid of
InstanceActionList object, also add limit/marker/filters support to
actions_get method of db.

Part of blueprint pagination-add-changes-since-for-instance-action-list

Change-Id: Ic7dd6480a4b250ae6529d94ee0386b5e95b0ca04
This commit is contained in:
Yikun Jiang 2017-12-07 09:33:04 -05:00 committed by Matt Riedemann
parent 1a4ae60e1b
commit 1950537a53
8 changed files with 99 additions and 17 deletions

View File

@ -1953,9 +1953,10 @@ def action_finish(context, values):
return IMPL.action_finish(context, values)
def actions_get(context, uuid):
"""Get all instance actions for the provided instance."""
return IMPL.actions_get(context, uuid)
def actions_get(context, instance_uuid, limit=None, marker=None,
filters=None):
"""Get all instance actions for the provided instance and filters."""
return IMPL.actions_get(context, instance_uuid, limit, marker, filters)
def action_get_by_request_id(context, uuid, request_id):

View File

@ -6227,12 +6227,30 @@ def action_finish(context, values):
@pick_context_manager_reader
def actions_get(context, instance_uuid):
"""Get all instance actions for the provided uuid."""
actions = model_query(context, models.InstanceAction).\
filter_by(instance_uuid=instance_uuid).\
order_by(desc("created_at"), desc("id")).\
all()
def actions_get(context, instance_uuid, limit=None, marker=None,
filters=None):
"""Get all instance actions for the provided uuid and filters."""
if limit == 0:
return []
sort_keys = ['created_at', 'id']
sort_dirs = ['desc', 'desc']
query_prefix = model_query(context, models.InstanceAction).\
filter_by(instance_uuid=instance_uuid)
if filters and 'changes-since' in filters:
changes_since = timeutils.normalize_time(filters['changes-since'])
query_prefix = query_prefix. \
filter(models.InstanceAction.updated_at >= changes_since)
if marker is not None:
marker = action_get_by_request_id(context, instance_uuid, marker)
if not marker:
raise exception.MarkerNotFound(marker=marker)
actions = sqlalchemyutils.paginate_query(query_prefix,
models.InstanceAction, limit,
sort_keys, marker=marker,
sort_dirs=sort_dirs).all()
return actions

View File

@ -100,15 +100,17 @@ class InstanceAction(base.NovaPersistentObject, base.NovaObject,
@base.NovaObjectRegistry.register
class InstanceActionList(base.ObjectListBase, base.NovaObject):
# Version 1.0: Initial version
# InstanceAction <= version 1.1
VERSION = '1.0'
# Version 1.1: get_by_instance_uuid added pagination and filters support
VERSION = '1.1'
fields = {
'objects': fields.ListOfObjectsField('InstanceAction'),
}
@base.remotable_classmethod
def get_by_instance_uuid(cls, context, instance_uuid):
db_actions = db.actions_get(context, instance_uuid)
def get_by_instance_uuid(cls, context, instance_uuid, limit=None,
marker=None, filters=None):
db_actions = db.actions_get(
context, instance_uuid, limit, marker, filters)
return base.obj_make_list(context, cls(), InstanceAction, db_actions)

View File

@ -42,7 +42,8 @@ class ServerActionsSampleJsonTest(api_sample_base.ApiSampleTestBaseV21):
def fake_instance_action_get_by_request_id(context, uuid, request_id):
return copy.deepcopy(self.actions[uuid][request_id])
def fake_server_actions_get(context, uuid):
def fake_server_actions_get(context, uuid, limit=None, marker=None,
filters=None):
return [copy.deepcopy(value) for value in
six.itervalues(self.actions[uuid])]

View File

@ -133,7 +133,8 @@ class InstanceActionsTestV21(test.NoDBTestCase):
policy.set_rules(oslo_policy.Rules.from_dict(rules))
def test_list_actions(self):
def fake_get_actions(context, uuid):
def fake_get_actions(context, uuid, limit=None, marker=None,
filters=None):
actions = []
for act in six.itervalues(self.fake_actions[uuid]):
action = models.InstanceAction()

View File

@ -4080,6 +4080,64 @@ class InstanceActionTestCase(test.TestCase, ModelsObjectComparatorMixin):
self._assertEqualOrderedListOfObjects([action2, action1], actions)
def test_instance_actions_get_with_limit(self):
"""Test list instance actions can support pagination."""
uuid1 = uuidsentinel.uuid1
extra = {
'created_at': timeutils.utcnow()
}
action_values = self._create_action_values(uuid1, extra=extra)
action1 = db.action_start(self.ctxt, action_values)
action_values['action'] = 'delete'
action_values['request_id'] = 'req-' + uuidsentinel.reqid1
db.action_start(self.ctxt, action_values)
actions = db.actions_get(self.ctxt, uuid1)
self.assertEqual(2, len(actions))
actions = db.actions_get(self.ctxt, uuid1, limit=1)
self.assertEqual(1, len(actions))
actions = db.actions_get(
self.ctxt, uuid1, limit=1,
marker=action_values['request_id'])
self.assertEqual(1, len(actions))
self._assertEqualListsOfObjects([action1], actions)
def test_instance_actions_get_with_changes_since(self):
"""Test list instance actions can support timestamp filter."""
uuid1 = uuidsentinel.uuid1
extra = {
'created_at': timeutils.utcnow()
}
action_values = self._create_action_values(uuid1, extra=extra)
db.action_start(self.ctxt, action_values)
timestamp = timeutils.utcnow()
action_values['start_time'] = timestamp
action_values['updated_at'] = timestamp
action_values['action'] = 'delete'
action2 = db.action_start(self.ctxt, action_values)
actions = db.actions_get(self.ctxt, uuid1)
self.assertEqual(2, len(actions))
self.assertNotEqual(actions[0]['updated_at'],
actions[1]['updated_at'])
actions = db.actions_get(
self.ctxt, uuid1, filters={'changes-since': timestamp})
self.assertEqual(1, len(actions))
self._assertEqualListsOfObjects([action2], actions)
def test_instance_actions_get_with_not_found_marker(self):
self.assertRaises(exception.MarkerNotFound,
db.actions_get, self.ctxt, uuidsentinel.uuid1,
marker=uuidsentinel.not_found_marker)
def test_instance_action_get_by_instance_and_action(self):
"""Ensure we can get an action by instance UUID and action id."""
ctxt2 = context.get_admin_context()

View File

@ -176,7 +176,8 @@ class _TestInstanceActionObject(object):
self.context, 'fake-uuid')
for index, action in enumerate(obj_list):
self.compare_obj(action, fake_actions[index])
mock_get.assert_called_once_with(self.context, 'fake-uuid')
mock_get.assert_called_once_with(self.context, 'fake-uuid', None,
None, None)
class TestInstanceActionObject(test_objects._LocalTest,

View File

@ -1102,7 +1102,7 @@ object_data = {
'InstanceAction': '1.1-f9f293e526b66fca0d05c3b3a2d13914',
'InstanceActionEvent': '1.1-e56a64fa4710e43ef7af2ad9d6028b33',
'InstanceActionEventList': '1.1-13d92fb953030cdbfee56481756e02be',
'InstanceActionList': '1.0-4a53826625cc280e15fae64a575e0879',
'InstanceActionList': '1.1-a2b2fb6006b47c27076d3a1d48baa759',
'InstanceDeviceMetadata': '1.0-74d78dd36aa32d26d2769a1b57caf186',
'InstanceExternalEvent': '1.2-23eb6ba79cde5cd06d3445f845ba4589',
'InstanceFault': '1.2-7ef01f16f1084ad1304a513d6d410a38',