Browse Source

Sanitize instance in InstanceMetadata to avoid un-pickleable context

This is a more strategic fix for the issue of us trying to pickle
an instance with a context that has complex data structures inside
(i.e. SQLAlchemy connections) into the oslo cache. The right solution
is for us to stop storing random python objects (InstanceMetadata)
in the cache with pickle. However, that's a larger change and more
complex for deployers to roll over. This attempts to sanitize the
instance before we pickle it to get things working again.

Change-Id: Ie7d97ce5c62c8fb9da5822590a64210521f8ae7a
Closes-Bug: #1694666
tags/16.0.0.0b3
Dan Smith 3 years ago
parent
commit
2fee972bde
2 changed files with 17 additions and 10 deletions
  1. +9
    -0
      nova/api/metadata/base.py
  2. +8
    -10
      nova/tests/unit/test_metadata.py

+ 9
- 0
nova/api/metadata/base.py View File

@@ -124,6 +124,15 @@ class InstanceMetadata(object):

ctxt = context.get_admin_context()

# NOTE(danms): Sanitize the instance to limit the amount of stuff
# inside that may not pickle well (i.e. context). We also touch
# some of the things we'll lazy load later to make sure we keep their
# values in what we cache.
instance.ec2_ids
instance.keypairs
instance = objects.Instance.obj_from_primitive(
instance.obj_to_primitive())

# The default value of mimeType is set to MIME_TYPE_TEXT_PLAIN
self.set_mimetype(MIME_TYPE_TEXT_PLAIN)
self.instance = instance


+ 8
- 10
nova/tests/unit/test_metadata.py View File

@@ -165,14 +165,6 @@ def fake_request(testcase, mdinst, relpath, address="127.0.0.1",
return response


class FakeDeviceMetadata(metadata_obj.DeviceMetadata):
pass


class FakeDeviceBus(metadata_obj.DeviceBus):
pass


def fake_metadata_objects():
nic_obj = metadata_obj.NetworkInterfaceMetadata(
bus=metadata_obj.PCIDeviceBus(address='0000:00:01.0'),
@@ -202,9 +194,9 @@ def fake_metadata_objects():
path='/dev/sda',
tags=['baz'],
)
fake_device_obj = FakeDeviceMetadata()
fake_device_obj = metadata_obj.DeviceMetadata()
device_with_fake_bus_obj = metadata_obj.NetworkInterfaceMetadata(
bus=FakeDeviceBus(),
bus=metadata_obj.DeviceBus(),
mac='00:00:00:00:00:00',
tags=['foo']
)
@@ -397,6 +389,12 @@ class MetadataTestCase(test.TestCase):
self.assertRaises(base.InvalidMetadataPath,
md.lookup, "/2009-04-04/meta-data/kernel-id")

def test_instance_is_sanitized(self):
inst = self.instance.obj_clone()
inst._will_not_pass = True
md = fake_InstanceMetadata(self, inst)
self.assertFalse(hasattr(md.instance, '_will_not_pass'))

def test_check_version(self):
inst = self.instance.obj_clone()
md = fake_InstanceMetadata(self, inst)


Loading…
Cancel
Save