Handle keypair not found from metadata server
With commit e83842b80b we
attempt to load keypairs for an instance from instance_extra,
but if that hasn't been migrated yet we fall back to loading
the keypair from the database by name.
If the keypair was deleted, the instance object will just set
an empty KeyPairList for instance.keypairs and we'll get an
IndexError when using self.instance.keypairs[0] in
_metadata_as_json.
This adds a check that instance.keypairs actually has
something in it. If not, we log a message and don't return
any key values in the metadata dict - same as if instance.key_name
wasn't set to begin with.
Change-Id: If823867d1df4bafa46978e62e05826d1f12c9269
Closes-Bug: #1592167
This commit is contained in:
@@ -306,17 +306,27 @@ class InstanceMetadata(object):
|
||||
context.get_admin_context(), self.instance.user_id,
|
||||
self.instance.key_name)
|
||||
else:
|
||||
keypair = self.instance.keypairs[0]
|
||||
keypairs = self.instance.keypairs
|
||||
# NOTE(mriedem): It's possible for the keypair to be deleted
|
||||
# before it was migrated to the instance_extra table, in which
|
||||
# case lazy-loading instance.keypairs will handle the 404 and
|
||||
# just set an empty KeyPairList object on the instance.
|
||||
keypair = keypairs[0] if keypairs else None
|
||||
|
||||
metadata['public_keys'] = {
|
||||
keypair.name: keypair.public_key,
|
||||
}
|
||||
if keypair:
|
||||
metadata['public_keys'] = {
|
||||
keypair.name: keypair.public_key,
|
||||
}
|
||||
|
||||
metadata['keys'] = [
|
||||
{'name': keypair.name,
|
||||
'type': keypair.type,
|
||||
'data': keypair.public_key}
|
||||
]
|
||||
metadata['keys'] = [
|
||||
{'name': keypair.name,
|
||||
'type': keypair.type,
|
||||
'data': keypair.public_key}
|
||||
]
|
||||
else:
|
||||
LOG.debug("Unable to find keypair for instance with "
|
||||
"key name '%s'.", self.instance.key_name,
|
||||
instance=self.instance)
|
||||
|
||||
metadata['hostname'] = self._get_hostname()
|
||||
metadata['name'] = self.instance.display_name
|
||||
|
||||
@@ -458,6 +458,21 @@ class MetadataTestCase(test.TestCase):
|
||||
self._test_as_json_with_options(is_cells=True,
|
||||
os_version=os_version)
|
||||
|
||||
@mock.patch.object(objects.Instance, 'get_by_uuid')
|
||||
def test_metadata_as_json_deleted_keypair(self, mock_inst_get_by_uuid):
|
||||
"""Tests that we handle missing instance keypairs.
|
||||
"""
|
||||
instance = self.instance.obj_clone()
|
||||
# we want to make sure that key_name is set but not keypairs so it has
|
||||
# to be lazy-loaded from the database
|
||||
delattr(instance, 'keypairs')
|
||||
mock_inst_get_by_uuid.return_value = instance
|
||||
md = fake_InstanceMetadata(self.stubs, instance)
|
||||
meta = md._metadata_as_json(base.OPENSTACK_VERSIONS[-1], path=None)
|
||||
meta = jsonutils.loads(meta)
|
||||
self.assertNotIn('keys', meta)
|
||||
self.assertNotIn('public_keys', meta)
|
||||
|
||||
|
||||
class OpenStackMetadataTestCase(test.TestCase):
|
||||
def setUp(self):
|
||||
|
||||
Reference in New Issue
Block a user