Aggregate ops on ProviderTree
Adds the following methods on ProviderTree: in_aggregates: whether a specified provider is a member of *all* aggregates in a given list have_aggregates_changed: whether a new set of aggregates differs from those already registered for a provider update_aggregates: set the list of aggregates with which a provider is associated, returning whether this effected a change Change-Id: Ibb90d05d7827a2f78860182e24d62ad41c57e581
This commit is contained in:
parent
f029350c89
commit
06976f887b
@ -49,6 +49,8 @@ class _Provider(object):
|
||||
self.inventory = {}
|
||||
# Set of trait names
|
||||
self.traits = set()
|
||||
# Set of aggregate UUIDs
|
||||
self.aggregates = set()
|
||||
|
||||
def get_provider_uuids(self):
|
||||
"""Returns a set of UUIDs of this provider and all its descendants."""
|
||||
@ -152,6 +154,31 @@ class _Provider(object):
|
||||
"""
|
||||
return not bool(set(traits) - self.traits)
|
||||
|
||||
def have_aggregates_changed(self, new):
|
||||
"""Returns whether the provider's aggregates have changed."""
|
||||
return set(new) != self.aggregates
|
||||
|
||||
def update_aggregates(self, new, generation=None):
|
||||
"""Update the stored aggregates for the provider along with a resource
|
||||
provider generation to set the provider to. The method returns whether
|
||||
the aggregates have changed.
|
||||
"""
|
||||
self._update_generation(generation)
|
||||
if self.have_aggregates_changed(new):
|
||||
self.aggregates = set(new) # create a copy of the new aggregates
|
||||
return True
|
||||
return False
|
||||
|
||||
def in_aggregates(self, aggregates):
|
||||
"""Query whether the provider is a member of certain aggregates.
|
||||
|
||||
:param aggregates: Iterable of string aggregate UUIDs to look for.
|
||||
:return: True if this provider is a member of *all* of the specified
|
||||
aggregates; False if any of the specified aggregates are
|
||||
absent. Returns True if the aggregates parameter is empty.
|
||||
"""
|
||||
return not bool(set(aggregates) - self.aggregates)
|
||||
|
||||
|
||||
class ProviderTree(object):
|
||||
|
||||
@ -352,3 +379,59 @@ class ProviderTree(object):
|
||||
with self.lock:
|
||||
provider = self._find_with_lock(name_or_uuid)
|
||||
return provider.update_traits(traits, generation=generation)
|
||||
|
||||
def in_aggregates(self, name_or_uuid, aggregates):
|
||||
"""Given a name or UUID of a provider, query whether that provider is a
|
||||
member of *all* the specified aggregates.
|
||||
|
||||
:raises: ValueError if a provider with name_or_uuid was not found in
|
||||
the tree.
|
||||
:param name_or_uuid: Either name or UUID of the resource provider to
|
||||
query for aggregates.
|
||||
:param aggregates: Iterable of string aggregate UUIDs to search for.
|
||||
:return: True if this provider is associated with *all* of the
|
||||
specified aggregates; False if any of the specified aggregates
|
||||
are absent. Returns True if the aggregates parameter is
|
||||
empty, even if the provider has no aggregate associations.
|
||||
"""
|
||||
with self.lock:
|
||||
provider = self._find_with_lock(name_or_uuid)
|
||||
return provider.in_aggregates(aggregates)
|
||||
|
||||
def have_aggregates_changed(self, name_or_uuid, aggregates):
|
||||
"""Returns True if the specified aggregates list is different for the
|
||||
provider with the specified name or UUID.
|
||||
|
||||
:raises: ValueError if a provider with name_or_uuid was not found in
|
||||
the tree.
|
||||
:param name_or_uuid: Either name or UUID of the resource provider to
|
||||
query aggregates for.
|
||||
:param aggregates: Iterable of string aggregate UUIDs to compare
|
||||
against the provider's aggregates.
|
||||
"""
|
||||
with self.lock:
|
||||
provider = self._find_with_lock(name_or_uuid)
|
||||
return provider.have_aggregates_changed(aggregates)
|
||||
|
||||
def update_aggregates(self, name_or_uuid, aggregates, generation=None):
|
||||
"""Given a name or UUID of a provider and an iterable of string
|
||||
aggregate UUIDs, update the provider's aggregates and set the
|
||||
provider's generation.
|
||||
|
||||
:returns: True if the aggregates list has changed.
|
||||
|
||||
:note: The provider's generation is always set to the supplied
|
||||
generation, even if there were no changes to the aggregates.
|
||||
|
||||
:raises: ValueError if a provider with name_or_uuid was not found in
|
||||
the tree.
|
||||
:param name_or_uuid: Either name or UUID of the resource provider to
|
||||
update aggregates for.
|
||||
:param aggregates: Iterable of string aggregate UUIDs to set.
|
||||
:param generation: The resource provider generation to set. If None,
|
||||
the provider's generation is not changed.
|
||||
"""
|
||||
with self.lock:
|
||||
provider = self._find_with_lock(name_or_uuid)
|
||||
return provider.update_aggregates(aggregates,
|
||||
generation=generation)
|
||||
|
@ -247,3 +247,54 @@ class TestProviderTree(test.NoDBTestCase):
|
||||
self.assertTrue(pt.update_traits(cn.uuid, traits))
|
||||
self.assertEqual(rp_gen, pt._find_with_lock(cn.uuid).generation)
|
||||
self.assertTrue(pt.has_traits(cn.uuid, traits[-1:]))
|
||||
|
||||
def test_have_aggregates_changed_no_existing_rp(self):
|
||||
cns = self.compute_nodes
|
||||
pt = provider_tree.ProviderTree(cns)
|
||||
self.assertRaises(
|
||||
ValueError, pt.have_aggregates_changed, uuids.non_existing_rp, [])
|
||||
|
||||
def test_update_aggregates_no_existing_rp(self):
|
||||
cns = self.compute_nodes
|
||||
pt = provider_tree.ProviderTree(cns)
|
||||
self.assertRaises(
|
||||
ValueError, pt.update_aggregates, uuids.non_existing_rp, [])
|
||||
|
||||
def test_have_aggregates_changed(self):
|
||||
cn = self.compute_node1
|
||||
cns = self.compute_nodes
|
||||
pt = provider_tree.ProviderTree(cns)
|
||||
rp_gen = 1
|
||||
|
||||
aggregates = [
|
||||
uuids.agg1,
|
||||
uuids.agg2,
|
||||
]
|
||||
self.assertTrue(pt.have_aggregates_changed(cn.uuid, aggregates))
|
||||
self.assertTrue(pt.in_aggregates(cn.uuid, []))
|
||||
self.assertFalse(pt.in_aggregates(cn.uuid, aggregates))
|
||||
self.assertFalse(pt.in_aggregates(cn.uuid, aggregates[:1]))
|
||||
self.assertTrue(pt.update_aggregates(cn.uuid, aggregates,
|
||||
generation=rp_gen))
|
||||
self.assertTrue(pt.in_aggregates(cn.uuid, aggregates))
|
||||
self.assertTrue(pt.in_aggregates(cn.uuid, aggregates[:1]))
|
||||
|
||||
# Updating with the same aggregates info should return False
|
||||
self.assertFalse(pt.have_aggregates_changed(cn.uuid, aggregates))
|
||||
# But the generation should get updated
|
||||
rp_gen = 2
|
||||
self.assertFalse(pt.update_aggregates(cn.uuid, aggregates,
|
||||
generation=rp_gen))
|
||||
self.assertFalse(pt.have_aggregates_changed(cn.uuid, aggregates))
|
||||
self.assertEqual(rp_gen, pt._find_with_lock(cn.uuid).generation)
|
||||
self.assertTrue(pt.in_aggregates(cn.uuid, aggregates))
|
||||
self.assertTrue(pt.in_aggregates(cn.uuid, aggregates[:1]))
|
||||
|
||||
# Make a change to the aggregates list
|
||||
aggregates.append(uuids.agg3)
|
||||
self.assertTrue(pt.have_aggregates_changed(cn.uuid, aggregates))
|
||||
self.assertFalse(pt.in_aggregates(cn.uuid, aggregates[-1:]))
|
||||
# Don't update the generation
|
||||
self.assertTrue(pt.update_aggregates(cn.uuid, aggregates))
|
||||
self.assertEqual(rp_gen, pt._find_with_lock(cn.uuid).generation)
|
||||
self.assertTrue(pt.in_aggregates(cn.uuid, aggregates[-1:]))
|
||||
|
Loading…
Reference in New Issue
Block a user