list_instances - cache allocations
When listing instances fetch all allocations to a cache, fetch each nodes allocation from the cache. This is significantly faster than calling get_allocation for each node. time metealsmith list # 250 nodes: real 0m54.970s vs real 1m45.048s without "cached". Story: 2010571 Task: 47318 Change-Id: Ic4cef61e338fb57bea5de4f96eb3584386cc5152
This commit is contained in:
parent
a71776b8a4
commit
364fa23916
|
@ -50,6 +50,8 @@ class Provisioner(object):
|
|||
OpenStack API during provisioning.
|
||||
"""
|
||||
|
||||
allocations_cache = dict()
|
||||
|
||||
def __init__(self, session=None, cloud_region=None, dry_run=False):
|
||||
if cloud_region is None:
|
||||
if session is None:
|
||||
|
@ -630,6 +632,8 @@ class Provisioner(object):
|
|||
:return: list of :py:class:`metalsmith.Instance` objects.
|
||||
"""
|
||||
nodes = self.connection.baremetal.nodes(associated=True, details=True)
|
||||
Provisioner.allocations_cache = {
|
||||
a.id: a for a in self.connection.baremetal.allocations()}
|
||||
instances = [i for i in map(self._get_instance, nodes)
|
||||
if i.state != _instance.InstanceState.UNKNOWN]
|
||||
return instances
|
||||
|
@ -678,13 +682,24 @@ class Provisioner(object):
|
|||
'with a node' % node)
|
||||
|
||||
def _get_instance(self, ident):
|
||||
node, allocation = self._find_node_and_allocation(ident)
|
||||
if allocation is None and node.allocation_id:
|
||||
if hasattr(ident, 'allocation_id'):
|
||||
node = ident
|
||||
try:
|
||||
allocation = self.connection.baremetal.get_allocation(
|
||||
node.allocation_id)
|
||||
try:
|
||||
allocation = Provisioner.allocations_cache[
|
||||
node.instance_id]
|
||||
except KeyError:
|
||||
allocation = self.connection.baremetal.get_allocation(
|
||||
node.allocation_id)
|
||||
except os_exc.ResourceNotFound as exc:
|
||||
raise exceptions.InstanceNotFound(str(exc))
|
||||
|
||||
else:
|
||||
node, allocation = self._find_node_and_allocation(ident)
|
||||
if allocation is None and node.allocation_id:
|
||||
try:
|
||||
allocation = self.connection.baremetal.get_allocation(
|
||||
node.allocation_id)
|
||||
except os_exc.ResourceNotFound as exc:
|
||||
raise exceptions.InstanceNotFound(str(exc))
|
||||
return _instance.Instance(self.connection, node,
|
||||
allocation=allocation)
|
||||
|
|
|
@ -32,6 +32,7 @@ NODE_FIELDS = ['name', 'id', 'instance_info', 'instance_id', 'is_maintenance',
|
|||
'maintenance_reason', 'properties', 'provision_state', 'extra',
|
||||
'last_error', 'traits', 'resource_class', 'conductor_group',
|
||||
'allocation_id']
|
||||
ALLOCATION_FIELDS = ['id', 'name', 'node_id']
|
||||
|
||||
|
||||
class TestInit(unittest.TestCase):
|
||||
|
@ -2073,14 +2074,16 @@ class TestListInstances(Base):
|
|||
self.nodes[0].allocation_id = 'id2'
|
||||
self.nodes[6].instance_id = None
|
||||
self.api.baremetal.nodes.return_value = self.nodes
|
||||
self.allocations = [mock.Mock(id='id2')]
|
||||
self.api.baremetal.allocations.return_value = self.allocations
|
||||
|
||||
def test_list(self):
|
||||
instances = self.pr.list_instances()
|
||||
self.assertTrue(all(isinstance(i, _instance.Instance)
|
||||
for i in instances))
|
||||
self.assertEqual(self.nodes[:6], [i.node for i in instances])
|
||||
self.assertEqual([self.api.baremetal.get_allocation.return_value]
|
||||
+ [None] * 5,
|
||||
self.assertEqual([self.api.baremetal.get_allocation.return_value] * 6,
|
||||
[i.allocation for i in instances])
|
||||
self.api.baremetal.nodes.assert_called_once_with(associated=True,
|
||||
details=True)
|
||||
self.api.baremetal.allocations.assert_called_once()
|
||||
|
|
Loading…
Reference in New Issue