re-orphan flavor after rpc deserialization
The flavor objects stored in the instance object should not be used to lazy load any data from the db as they are not connected to real flavors in the db. These flavor objects are orphaned when created but durin rpc deserialization every deserialized nova object automatically gets a valid context. This can lead to unintended lazy loading of the projects field of such flavor objects during notification payload generation. This patch orphans the flavor objects stored in the instance object after every deserialization. Change-Id: I458f81931bad7874e951e1c0fd464d149f61b244 Related-Bug: #1653221
This commit is contained in:
parent
cb01463af4
commit
0082c47896
@ -272,6 +272,19 @@ class Instance(base.NovaPersistentObject, base.NovaObject,
|
||||
self = super(Instance, cls)._obj_from_primitive(context, objver,
|
||||
primitive)
|
||||
self._reset_metadata_tracking()
|
||||
|
||||
# Note(gibi): The flavors stored in the instance should not be used
|
||||
# for lazy load data from the db as these objects aren't connected to
|
||||
# real flavor objects in the db. However during RPC deserialization
|
||||
# every object gets a valid context so we have to orphan the flavors
|
||||
# again.
|
||||
if self.obj_attr_is_set('flavor'):
|
||||
self.flavor._context = None
|
||||
if self.obj_attr_is_set('old_flavor') and self.old_flavor:
|
||||
self.old_flavor._context = None
|
||||
if self.obj_attr_is_set('new_flavor') and self.new_flavor:
|
||||
self.new_flavor._context = None
|
||||
|
||||
return self
|
||||
|
||||
@property
|
||||
|
@ -1518,6 +1518,30 @@ class _TestInstanceObject(object):
|
||||
inst1 = inst1.obj_clone()
|
||||
self.assertEqual(len(inst1.obj_what_changed()), 0)
|
||||
|
||||
def test_flavor_deserialization_orphans_flavor(self):
|
||||
flavor = objects.Flavor(context=self.context,
|
||||
name='test-flavor',
|
||||
memory_mb=1024,
|
||||
root_gb=0,
|
||||
vcpus=1,
|
||||
flavorid="m1.test")
|
||||
flavor.create()
|
||||
inst = objects.Instance(context=self.context,
|
||||
user_id=self.context.user_id,
|
||||
project_id=self.context.project_id,
|
||||
flavor=flavor,
|
||||
old_flavor=flavor,
|
||||
new_flavor=flavor)
|
||||
inst.create()
|
||||
|
||||
inst = objects.Instance.get_by_uuid(self.context,
|
||||
uuid=inst.uuid,
|
||||
expected_attrs=['flavor'])
|
||||
|
||||
self.assertIsNone(inst.flavor._context)
|
||||
self.assertIsNone(inst.old_flavor._context)
|
||||
self.assertIsNone(inst.new_flavor._context)
|
||||
|
||||
|
||||
class TestInstanceObject(test_objects._LocalTest,
|
||||
_TestInstanceObject):
|
||||
|
Loading…
x
Reference in New Issue
Block a user