placement: filtering the resource provider id when delete trait association

When delete a trait association for specific resource provider, the current
code will delete that trait associations for all the resource providers.

The expected behaviour is only the specific trait association for the
specific resource provider will be removed. This patch corrects the filter
for the deletion of trait association.

Change-Id: I4b8f1b8f0a8d16f1c415edbfb2a7d342d176f70a
Closes-Bug: #1708978
This commit is contained in:
He Jie Xu 2017-07-31 21:07:17 +08:00
parent 008bc0b971
commit e66c1accbd
2 changed files with 44 additions and 1 deletions

View File

@ -644,7 +644,12 @@ class ResourceProvider(base.NovaObject):
with conn.begin():
if to_delete_names:
context.session.query(models.ResourceProviderTrait).filter(
models.ResourceProviderTrait.trait_id.in_(to_delete_ids)
sa.and_(
models.ResourceProviderTrait.trait_id.in_(
to_delete_ids),
(models.ResourceProviderTrait.resource_provider_id ==
_id)
)
).delete(synchronize_session='fetch')
if to_add_names:
for name in to_add_names:

View File

@ -1763,6 +1763,44 @@ class ResourceProviderTraitTestCase(ResourceProviderBaseCase):
self._assert_traits(trait_names, rp.get_traits())
self.assertEqual(rp.generation, generation + 1)
def test_set_traits_for_correct_resource_provider(self):
"""This test creates two ResourceProviders, and attaches same trait to
both of them. Then detaching the trait from one of them, and ensure
the trait still associated with another one.
"""
# Create two ResourceProviders
rp1 = objects.ResourceProvider(
context=self.ctx,
uuid=uuidsentinel.fake_resource_provider1,
name=uuidsentinel.fake_resource_name1,
)
rp1.create()
rp2 = objects.ResourceProvider(
context=self.ctx,
uuid=uuidsentinel.fake_resource_provider2,
name=uuidsentinel.fake_resource_name2,
)
rp2.create()
# Create a trait
t = objects.Trait(self.ctx)
t.name = 'CUSTOM_TRAIT_A'
t.create()
# Associate the trait with two ResourceProviders
rp1.set_traits([t])
rp2.set_traits([t])
# Ensure the association
self._assert_traits(['CUSTOM_TRAIT_A'], rp1.get_traits())
self._assert_traits(['CUSTOM_TRAIT_A'], rp2.get_traits())
# Detach the trait from one of ResourceProvider, and ensure the
# trait association with another ResourceProvider still exists.
rp1.set_traits([])
self._assert_traits([], rp1.get_traits())
self._assert_traits(['CUSTOM_TRAIT_A'], rp2.get_traits())
def test_trait_delete_in_use(self):
rp = objects.ResourceProvider(
context=self.ctx,