From fc225f16a12471bfde9d5d0d378e69fba201e58a Mon Sep 17 00:00:00 2001 From: Takashi NATSUME Date: Wed, 1 Nov 2017 14:03:12 +0900 Subject: [PATCH] [placement] Fix foreign key constraint error When deleting a resource provider, if there are traits on the resource provider, a foreign key constraint error occurs. So add deleting trait associations for the resource provider (records in the 'resource_provider_traits' table) when deleting the resource provider. Conflicts: nova/objects/resource_provider.py NOTE(mriedem): The conflict is due to changes introduced by b10f11d7e8e1afb7a12a470f92c42bf3c23eca95 in Queens which are not needed in Pike. The test also needed to change since 1df5aad91017b4a7ef51fb6efac29e671f7cc7eb is not in Pike. Change-Id: I6874567a14beb9b029765bf49067af6de17f2bd2 Closes-Bug: #1727719 (cherry picked from commit 5de3317d68df8fdc6fdaff62baa62822c669bb93) --- nova/objects/resource_provider.py | 4 +++ .../unit/objects/test_resource_provider.py | 29 +++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/nova/objects/resource_provider.py b/nova/objects/resource_provider.py index 8a39d046c960..16ef01d5aa76 100644 --- a/nova/objects/resource_provider.py +++ b/nova/objects/resource_provider.py @@ -505,6 +505,10 @@ class ResourceProvider(base.NovaObject): RPA_model = models.ResourceProviderAggregate context.session.query(RPA_model).\ filter(RPA_model.resource_provider_id == _id).delete() + # delete any trait associations for the resource provider + RPT_model = models.ResourceProviderTrait + context.session.query(RPT_model).\ + filter(RPT_model.resource_provider_id == _id).delete() # Now delete the RP records result = context.session.query(models.ResourceProvider).\ filter(models.ResourceProvider.id == _id).delete() diff --git a/nova/tests/unit/objects/test_resource_provider.py b/nova/tests/unit/objects/test_resource_provider.py index 746a9257bf1e..f0a43be78fba 100644 --- a/nova/tests/unit/objects/test_resource_provider.py +++ b/nova/tests/unit/objects/test_resource_provider.py @@ -140,6 +140,35 @@ class TestResourceProvider(test_objects._LocalTest): objects.ResourceProvider.get_by_uuid, self.context, uuids.missing) + def test_destroy_with_traits(self): + """Test deleting a resource provider that has a trait successfully. + """ + rp = resource_provider.ResourceProvider(self.context, + uuid=uuids.rp, + name='fake_rp1') + rp.create() + custom_trait = resource_provider.Trait(self.context, + uuid=uuids.trait, + name='CUSTOM_TRAIT_1') + custom_trait.create() + rp.set_traits([custom_trait]) + + trl = rp.get_traits() + self.assertEqual(1, len(trl)) + + # Delete a resource provider that has a trait assosiation. + rp.destroy() + + # Assert the record has been deleted + # in 'resource_provider_traits' table + # after Resource Provider object has been destroyed. + trl = rp.get_traits() + self.assertEqual(0, len(trl)) + # Assert that NotFound exception is raised. + self.assertRaises(exception.NotFound, + resource_provider.ResourceProvider.get_by_uuid, + self.context, uuids.rp) + class TestInventoryNoDB(test_objects._LocalTest): USES_DB = False