diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index 178af9d05234..6532548dda82 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -5805,6 +5805,7 @@ def _action_get_by_request_id(context, instance_uuid, request_id): result = model_query(context, models.InstanceAction).\ filter_by(instance_uuid=instance_uuid).\ filter_by(request_id=request_id).\ + order_by(desc("created_at"), desc("id")).\ first() return result diff --git a/nova/tests/unit/db/test_db_api.py b/nova/tests/unit/db/test_db_api.py index 030e05e4ec60..e332c5f22c82 100644 --- a/nova/tests/unit/db/test_db_api.py +++ b/nova/tests/unit/db/test_db_api.py @@ -3851,11 +3851,12 @@ class InstanceActionTestCase(test.TestCase, ModelsObjectComparatorMixin): self.ctxt = context.get_admin_context() def _create_action_values(self, uuid, action='run_instance', - ctxt=None, extra=None): + ctxt=None, extra=None, instance_create=True): if ctxt is None: ctxt = self.ctxt - db.instance_create(ctxt, {'uuid': uuid}) + if instance_create: + db.instance_create(ctxt, {'uuid': uuid}) utc_now = timeutils.utcnow() values = { @@ -4060,6 +4061,34 @@ class InstanceActionTestCase(test.TestCase, ModelsObjectComparatorMixin): self.assertEqual('run_instance', action['action']) self.assertEqual(self.ctxt.request_id, action['request_id']) + def test_instance_action_get_by_instance_and_action_by_order(self): + instance_uuid = uuidsentinel.uuid1 + + t1 = { + 'created_at': timeutils.utcnow() + } + t2 = { + 'created_at': timeutils.utcnow() + datetime.timedelta(seconds=5) + } + # Create a confirmResize action + action_values = self._create_action_values( + instance_uuid, action='confirmResize', extra=t1) + a1 = db.action_start(self.ctxt, action_values) + + # Create a delete action with same instance uuid and req id + action_values = self._create_action_values( + instance_uuid, action='delete', extra=t2, instance_create=False) + a2 = db.action_start(self.ctxt, action_values) + + self.assertEqual(a1['request_id'], a2['request_id']) + self.assertEqual(a1['instance_uuid'], a2['instance_uuid']) + self.assertTrue(a1['created_at'] < a2['created_at']) + + action = db.action_get_by_request_id(self.ctxt, instance_uuid, + a1['request_id']) + # Only get the delete action(last created) + self.assertEqual(action['action'], a2['action']) + def test_instance_action_event_start(self): """Create an instance action event.""" uuid = uuidsentinel.uuid1