ProviderTree.get_provider_uuids()

As we start using nested resource providers in the resource tracker, and
virt drivers, we're going to need to be able to e.g. diff provider trees
and create or delete entries in placement accordingly.  This change set
implements get_provider_uuids() on ProviderTree, which returns a set of
the UUIDs of all providers, optionally at and below the level of a
provider specified by name or UUID.  So you can say e.g.:

 uuids_to_delete = old.get_provider_uuids() - new.get_provider_uuids()

or

 numa1_uuids = ptree.get_provider_uuids(name_or_uuid=numa_cell_1_uuid)

Change-Id: I994442830588ee37eda409370a07152903b2e817
blueprint: nested-resource-providers
This commit is contained in:
Eric Fried 2017-11-29 11:14:54 -06:00
parent 1f41326ee6
commit 2a5fd148b9
2 changed files with 40 additions and 0 deletions

View File

@ -48,6 +48,13 @@ class _Provider(object):
# dict of inventory records, keyed by resource class
self.inventory = {}
def get_provider_uuids(self):
"""Returns a set of UUIDs of this provider and all its descendants."""
ret = set([self.uuid])
for child in self.children.values():
ret |= child.get_provider_uuids()
return ret
def find(self, search):
if self.name == search or self.uuid == search:
return self
@ -129,6 +136,25 @@ class ProviderTree(object):
p = _Provider(cn.hypervisor_hostname, cn.uuid)
self.roots.append(p)
def get_provider_uuids(self, name_or_uuid=None):
"""Return a set of the UUIDs of all providers (in a subtree).
:param name_or_uuid: Provider name or UUID representing the root of a
subtree for which to return UUIDs. If not
specified, the method returns all UUIDs in the
ProviderTree.
"""
if name_or_uuid is not None:
with self.lock:
return self._find_with_lock(name_or_uuid).get_provider_uuids()
# If no name_or_uuid, get UUIDs for all providers recursively.
ret = set()
with self.lock:
for root in self.roots:
ret |= root.get_provider_uuids()
return ret
def remove(self, name_or_uuid):
"""Safely removes the provider identified by the supplied name_or_uuid
parameter and all of its children from the tree.

View File

@ -34,6 +34,7 @@ class TestProviderTree(test.NoDBTestCase):
def test_tree_ops(self):
cn1 = self.compute_node1
cn2 = self.compute_node2
cns = self.compute_nodes
pt = provider_tree.ProviderTree(cns)
@ -50,6 +51,10 @@ class TestProviderTree(test.NoDBTestCase):
self.assertFalse(pt.exists(uuids.non_existing_rp))
self.assertFalse(pt.exists('noexist'))
self.assertEqual(set([cn1.uuid]),
pt.get_provider_uuids(name_or_uuid=cn1.uuid))
self.assertEqual(set([cn1.uuid, cn2.uuid]), pt.get_provider_uuids())
numa_cell0_uuid = pt.new_child('numa_cell0', cn1.uuid)
numa_cell1_uuid = pt.new_child('numa_cell1', cn1.uuid)
@ -63,6 +68,15 @@ class TestProviderTree(test.NoDBTestCase):
self.assertTrue(pt.exists(pf1_cell0_uuid))
self.assertTrue(pt.exists('pf1_cell0'))
# Now we've got a 3-level tree under cn1 - check provider UUIDs again
self.assertEqual(
set([cn1.uuid, numa_cell0_uuid, pf1_cell0_uuid, numa_cell1_uuid]),
pt.get_provider_uuids(name_or_uuid=cn1.uuid))
self.assertEqual(
set([cn1.uuid, cn2.uuid, numa_cell0_uuid, pf1_cell0_uuid,
numa_cell1_uuid]),
pt.get_provider_uuids())
self.assertRaises(
ValueError,
pt.new_child,