From cc75f91aac22199419cc64959cf86e3d41ac5b20 Mon Sep 17 00:00:00 2001 From: melanie witt Date: Wed, 17 May 2023 03:04:49 +0000 Subject: [PATCH] Add debug logging when Instance raises OrphanedObjectError This logging would be helpful in debugging issues when OrphanedObjectError is raised by an instance. Currently, there is not a way to identify which instance is attempting to lazy-load a field while orphaned. Being able to locate the instance in the database could also help with recovery/cleanup when a problematic record is disrupting operation of a deployment. Change-Id: I093de2839c1bb7c949a0812e07b63de4cc5ed167 (cherry picked from commit e0fbb6fc06d3b08b938af2e36b11f04c57fe6954) (cherry picked from commit f32deaa617286e4b0dc2d01585ccb5ac821a571c) (cherry picked from commit 9e8456297681ad21680acd35718e3cb97f8458f2) (cherry picked from commit 8aa6723fa4355c9e609ab449c28ea3cbe356c839) --- nova/objects/instance.py | 5 +++++ nova/tests/unit/objects/test_instance.py | 15 +++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/nova/objects/instance.py b/nova/objects/instance.py index 578b6ce37901..fe5d8c5f81af 100644 --- a/nova/objects/instance.py +++ b/nova/objects/instance.py @@ -1088,6 +1088,11 @@ class Instance(base.NovaPersistentObject, base.NovaObject, def obj_load_attr(self, attrname): # NOTE(danms): We can't lazy-load anything without a context and a uuid if not self._context: + if 'uuid' in self: + LOG.debug( + "Lazy-load of '%s' attempted by orphaned instance", + attrname, instance=self + ) raise exception.OrphanedObjectError(method='obj_load_attr', objtype=self.obj_name()) if 'uuid' not in self: diff --git a/nova/tests/unit/objects/test_instance.py b/nova/tests/unit/objects/test_instance.py index e187a4c251c2..cbe8c3e6f682 100644 --- a/nova/tests/unit/objects/test_instance.py +++ b/nova/tests/unit/objects/test_instance.py @@ -1632,6 +1632,21 @@ class TestInstanceObject(test_objects._LocalTest, self._test_save_objectfield_fk_constraint_fails( 'other_foreign_key', db_exc.DBReferenceError) + @mock.patch('nova.objects.instance.LOG.debug') + def test_obj_load_attr_log(self, mock_log_debug): + # Instance with no UUID should not log. + instance = objects.Instance() + self.assertRaises( + exception.OrphanedObjectError, instance.obj_load_attr, 'foo') + mock_log_debug.assert_not_called() + # Instance with UUID should log. + instance = objects.Instance( + uuid='127a0d59-b88c-422b-b9a1-2dc7cc51fb9a') + self.assertRaises( + exception.OrphanedObjectError, instance.obj_load_attr, 'foo') + msg = "Lazy-load of '%s' attempted by orphaned instance" + mock_log_debug.assert_called_once_with(msg, 'foo', instance=instance) + class TestRemoteInstanceObject(test_objects._RemoteTest, _TestInstanceObject):