Use cell targeted context to query BDMs for metadata

The metadata service supports a multicell deployment in a configuration
where the nova-api service implements the metadata API. In this case the
metadata query needs to be cell targeted. This was partly implemented
already. The instance itself is queried from the cell DB properly.
However the BDM data used the non targeted context resulting in an empty
BDM returned by the metadata service.

Functional reproduction test is not added as I did not find a way to
have a cell setup in the functional test that reproduce the problem. I
reproduced the bug and tested the fix in a devstack.

Change-Id: I48f57082edaef3ec4722bd31ce29a90b94d32523
Closes-Bug: #1881944
(cherry picked from commit 1390eecf8d)
(cherry picked from commit 9a5b6249d6)
(cherry picked from commit c727cfc36c)
This commit is contained in:
Balazs Gibizer 2020-09-21 17:21:18 +02:00
parent b2037fc4e3
commit 4839d41fc0
2 changed files with 17 additions and 11 deletions

View File

@ -122,8 +122,13 @@ class InstanceMetadata(object):
if not content:
content = []
# NOTE(gibi): this is not a cell targeted context even if we are called
# in a situation when the instance is in a different cell than the
# metadata service itself.
ctxt = context.get_admin_context()
self.mappings = _format_instance_mapping(instance)
# 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
@ -145,8 +150,6 @@ class InstanceMetadata(object):
self.security_groups = secgroup_api.get_instance_security_groups(
ctxt, instance)
self.mappings = _format_instance_mapping(ctxt, instance)
if instance.user_data is not None:
self.userdata_raw = base64.decode_as_bytes(instance.user_data)
else:
@ -683,9 +686,8 @@ def get_metadata_by_instance_id(instance_id, address, ctxt=None):
return InstanceMetadata(instance, address)
def _format_instance_mapping(ctxt, instance):
bdms = objects.BlockDeviceMappingList.get_by_instance_uuid(
ctxt, instance.uuid)
def _format_instance_mapping(instance):
bdms = instance.get_bdms()
return block_device.instance_block_mapping(instance, bdms)

View File

@ -329,12 +329,14 @@ class MetadataTestCase(test.TestCase):
'uuid': 'e5fe5518-0288-4fa3-b0c4-c79764101b85',
'root_device_name': None,
'default_ephemeral_device': None,
'default_swap_device': None})
'default_swap_device': None,
'context': self.context})
instance_ref1 = objects.Instance(**{'id': 0,
'uuid': 'b65cee2f-8c69-4aeb-be2f-f79742548fc2',
'root_device_name': '/dev/sda1',
'default_ephemeral_device': None,
'default_swap_device': None})
'default_swap_device': None,
'context': self.context})
def fake_bdm_get(ctxt, uuid):
return [fake_block_device.FakeDbBlockDeviceDict(
@ -373,10 +375,12 @@ class MetadataTestCase(test.TestCase):
'swap': '/dev/sdc',
'ebs0': '/dev/sdh'}
self.assertEqual(base._format_instance_mapping(self.context,
instance_ref0), block_device._DEFAULT_MAPPINGS)
self.assertEqual(base._format_instance_mapping(self.context,
instance_ref1), expected)
self.assertEqual(
base._format_instance_mapping(instance_ref0),
block_device._DEFAULT_MAPPINGS)
self.assertEqual(
base._format_instance_mapping(instance_ref1),
expected)
def test_pubkey(self):
md = fake_InstanceMetadata(self, self.instance.obj_clone())