From e2924ba2379adc19e7ebd07ead8efd5e9c8e367d Mon Sep 17 00:00:00 2001 From: Eric Fried Date: Sat, 31 Mar 2018 11:42:52 -0500 Subject: [PATCH] Use an independent transaction for _trait_sync Provides a fix for the referenced bug by using an independent transaction for the _trait_sync method, meaning it gets committed right away regardless of what happens in the calling scope. Change-Id: Ie9731d0df8cf52acdc7a442316a35798a4fed4cb Closes-Bug: 1760322 --- .../placement/objects/resource_provider.py | 4 +++- .../placement/db/test_resource_provider.py | 15 ++++++--------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/nova/api/openstack/placement/objects/resource_provider.py b/nova/api/openstack/placement/objects/resource_provider.py index 3816b70143ca..5572188ddf3e 100644 --- a/nova/api/openstack/placement/objects/resource_provider.py +++ b/nova/api/openstack/placement/objects/resource_provider.py @@ -78,7 +78,9 @@ def _ensure_rc_cache(ctx): @oslo_db_api.wrap_db_retry(max_retries=5, retry_on_deadlock=True) -@db_api.api_context_manager.writer +# Bug #1760322: If the caller raises an exception, we don't want the trait +# sync rolled back; so use an .independent transaction +@db_api.api_context_manager.writer.independent def _trait_sync(ctx): """Sync the os_traits symbols to the database. diff --git a/nova/tests/functional/api/openstack/placement/db/test_resource_provider.py b/nova/tests/functional/api/openstack/placement/db/test_resource_provider.py index a957424a99c8..5d03a702108b 100644 --- a/nova/tests/functional/api/openstack/placement/db/test_resource_provider.py +++ b/nova/tests/functional/api/openstack/placement/db/test_resource_provider.py @@ -2258,19 +2258,16 @@ class ResourceProviderTraitTestCase(ResourceProviderBaseCase): rp_obj.Trait.get_by_name, self.ctx, 'CUSTOM_TRAIT_A') def test_bug_1760322(self): - # If the first hit to the traits table results in an exception, the - # sync transaction rolls back and the table stays empty. But - # _TRAITS_SYNCED got set to True, so it doesn't resync next time. + # Under bug # #1760322, if the first hit to the traits table resulted + # in an exception, the sync transaction rolled back and the table + # stayed empty; but _TRAITS_SYNCED got set to True, so it didn't resync + # next time. try: rp_obj.Trait.get_by_name(self.ctx, 'CUSTOM_GOLD') except exception.TraitNotFound: pass - # FIXME(efried): Bug #1760322: Should still succeed for a "real" trait. - # rp_obj.Trait.get_by_name(self.ctx, os_traits.HW_CPU_X86_AVX2) - # ...but instead raises TraitNotFound. - self.assertRaises( - exception.TraitNotFound, - rp_obj.Trait.get_by_name, self.ctx, os_traits.HW_CPU_X86_AVX2) + # Under bug #1760322, this raised TraitNotFound. + rp_obj.Trait.get_by_name(self.ctx, os_traits.HW_CPU_X86_AVX2) def test_trait_destroy(self): t = rp_obj.Trait(self.ctx)