Default embedded instance.flavor.is_public attribute

It is possible that really old instances don't actually have this
attribute defined which can lead to raising exceptions when loading
their embedded flavors from the database.

This patch fixes this by defaulting these values to true if they
are not set.

Change-Id: If04cd802ce7184dc94f94804c743faebe0d4bd8c
Closes-Bug: #1789423
(cherry picked from commit c4f6b0bf6c)
(cherry picked from commit c689c09996)
(cherry picked from commit 61bf7ae579)
(cherry picked from commit 9a0d338c67)
This commit is contained in:
Mohammed Naser 2018-11-02 12:21:26 +01:00 committed by Matt Riedemann
parent 8c663dbd25
commit b8702ded74
2 changed files with 19 additions and 11 deletions

View File

@ -318,29 +318,31 @@ class Instance(base.NovaPersistentObject, base.NovaObject,
# Before we stored flavors in instance_extra, certain fields, defined
# in nova.compute.flavors.system_metadata_flavor_props, were stored
# in the instance.system_metadata for the embedded instance.flavor.
# The "disabled" field wasn't one of those keys, however, so really
# old instances that had their embedded flavor converted to the
# serialized instance_extra form won't have the disabled attribute
# set and we need to default those here so callers don't explode trying
# to load instance.flavor.disabled.
def _default_disabled(flavor):
# The "disabled" and "is_public" fields weren't one of those keys,
# however, so really old instances that had their embedded flavor
# converted to the serialized instance_extra form won't have the
# disabled attribute set and we need to default those here so callers
# don't explode trying to load instance.flavor.disabled.
def _default_flavor_values(flavor):
if 'disabled' not in flavor:
flavor.disabled = False
if 'is_public' not in flavor:
flavor.is_public = True
flavor_info = jsonutils.loads(db_flavor)
self.flavor = objects.Flavor.obj_from_primitive(flavor_info['cur'])
_default_disabled(self.flavor)
_default_flavor_values(self.flavor)
if flavor_info['old']:
self.old_flavor = objects.Flavor.obj_from_primitive(
flavor_info['old'])
_default_disabled(self.old_flavor)
_default_flavor_values(self.old_flavor)
else:
self.old_flavor = None
if flavor_info['new']:
self.new_flavor = objects.Flavor.obj_from_primitive(
flavor_info['new'])
_default_disabled(self.new_flavor)
_default_flavor_values(self.new_flavor)
else:
self.new_flavor = None
self.obj_reset_changes(['flavor', 'old_flavor', 'new_flavor'])

View File

@ -339,8 +339,10 @@ class _TestInstanceObject(object):
# make sure we default the "new" flavor's disabled value to False on
# load from the database.
fake_flavor = jsonutils.dumps(
{'cur': objects.Flavor(disabled=False).obj_to_primitive(),
'old': objects.Flavor(disabled=True).obj_to_primitive(),
{'cur': objects.Flavor(disabled=False,
is_public=True).obj_to_primitive(),
'old': objects.Flavor(disabled=True,
is_public=False).obj_to_primitive(),
'new': objects.Flavor().obj_to_primitive()})
fake_inst = dict(self.fake_instance, extra={'flavor': fake_flavor})
mock_get.return_value = fake_inst
@ -348,6 +350,10 @@ class _TestInstanceObject(object):
self.assertFalse(inst.flavor.disabled)
self.assertTrue(inst.old_flavor.disabled)
self.assertFalse(inst.new_flavor.disabled)
# Assert the is_public values on the flavors
self.assertTrue(inst.flavor.is_public)
self.assertFalse(inst.old_flavor.is_public)
self.assertTrue(inst.new_flavor.is_public)
@mock.patch.object(db, 'instance_get_by_uuid')
def test_get_remote(self, mock_get):