Merge "Don't lazy-load flavor.projects during destroy()"
This commit is contained in:
commit
28ace935cd
@ -17,7 +17,7 @@
|
||||
"vcpu_weight": 0,
|
||||
"flavorid": "a22d5517-147c-4147-a0d1-e698df5cd4e3",
|
||||
"extra_specs": null,
|
||||
"projects": []
|
||||
"projects": null
|
||||
}
|
||||
},
|
||||
"event_type": "flavor.delete",
|
||||
|
@ -614,6 +614,11 @@ class Flavor(base.NovaPersistentObject, base.NovaObject,
|
||||
# lazy-load projects (which is a problem for instance-bound
|
||||
# flavors and compute-cell operations), just load them here.
|
||||
if 'projects' not in self:
|
||||
# If the flavor is deleted we can't lazy-load projects.
|
||||
# FlavorPayload will orphan the flavor which will make the
|
||||
# NotificationPayloadBase set projects=None in the notification
|
||||
# payload.
|
||||
if action != fields.NotificationAction.DELETE:
|
||||
self._load_projects()
|
||||
notification_type = flavor_notification.FlavorNotification
|
||||
payload_type = flavor_notification.FlavorPayload
|
||||
|
@ -21,6 +21,8 @@ from nova.objects import fields
|
||||
from nova import test
|
||||
from nova.tests.unit.objects.test_flavor import fake_flavor
|
||||
|
||||
PROJECTS_SENTINEL = object()
|
||||
|
||||
|
||||
class TestFlavorNotification(test.TestCase):
|
||||
def setUp(self):
|
||||
@ -29,7 +31,8 @@ class TestFlavorNotification(test.TestCase):
|
||||
|
||||
@mock.patch('nova.notifications.objects.flavor.FlavorNotification')
|
||||
def _verify_notification(self, flavor_obj, flavor, action,
|
||||
mock_notification, project_id=None):
|
||||
mock_notification, project_id=None,
|
||||
expected_projects=PROJECTS_SENTINEL):
|
||||
notification = mock_notification
|
||||
if action == "CREATE":
|
||||
flavor_obj.create()
|
||||
@ -61,8 +64,12 @@ class TestFlavorNotification(test.TestCase):
|
||||
|
||||
schema = flavor_notification.FlavorPayload.SCHEMA
|
||||
for field in schema:
|
||||
if field in flavor:
|
||||
self.assertEqual(flavor[field], getattr(payload, field))
|
||||
if field == 'projects' and expected_projects != PROJECTS_SENTINEL:
|
||||
self.assertEqual(expected_projects, getattr(payload, field))
|
||||
elif field in flavor_obj:
|
||||
self.assertEqual(flavor_obj[field], getattr(payload, field))
|
||||
else:
|
||||
self.fail('Missing check for field %s in flavor_obj.' % field)
|
||||
|
||||
@mock.patch('nova.objects.Flavor._flavor_create')
|
||||
def test_flavor_create_with_notification(self, mock_create):
|
||||
@ -117,6 +124,26 @@ class TestFlavorNotification(test.TestCase):
|
||||
mock_destroy.return_value = flavor
|
||||
flavor_obj = objects.Flavor(context=self.ctxt, **flavor)
|
||||
flavor_obj.obj_reset_changes()
|
||||
self.assertNotIn('projects', flavor_obj)
|
||||
# We specifically expect there to not be any projects as we don't want
|
||||
# to try and lazy-load them from the main database and end up with [].
|
||||
self._verify_notification(flavor_obj, flavor, "DELETE",
|
||||
expected_projects=None)
|
||||
|
||||
@mock.patch('nova.objects.Flavor._flavor_destroy')
|
||||
def test_flavor_destroy_with_notification_and_projects(self, mock_destroy):
|
||||
"""Tests the flavor-delete notification with flavor.projects loaded."""
|
||||
flavor = copy.deepcopy(fake_flavor)
|
||||
flavorid = '1'
|
||||
flavor['flavorid'] = flavorid
|
||||
flavor['id'] = flavorid
|
||||
mock_destroy.return_value = flavor
|
||||
flavor_obj = objects.Flavor(
|
||||
context=self.ctxt, projects=['foo'], **flavor)
|
||||
flavor_obj.obj_reset_changes()
|
||||
self.assertIn('projects', flavor_obj)
|
||||
self.assertEqual(['foo'], flavor_obj.projects)
|
||||
# Since projects is loaded we shouldn't try to lazy-load it.
|
||||
self._verify_notification(flavor_obj, flavor, "DELETE")
|
||||
|
||||
def test_obj_make_compatible(self):
|
||||
|
Loading…
Reference in New Issue
Block a user